<!DOCTYPE html>


<html lang="zh-CN">


<head>
  <meta charset="utf-8" />
  <meta name="baidu_union_verify" content="0423ec0cdca4f8eebe6e059172fc0e94">
  <meta name="baidu-site-verification" content="code-pR8Cu8CCAR" />
  <meta name="google-site-verification" content="kPx7uwBYN8ZNVw-1hPQgk5yziYYGu7ZawLlYvgTblwQ" />
  <meta name="sogou_site_verification" content="bt3Su26Lme"/>
  <meta name="360-site-verification" content="73ba99e99d3fc1e5f8a37d8c1d998703" />
   
  <meta name="keywords" content="LIEFox,liefox,liefox拾柒,LIEFox拾柒,编程笔记,JAVA,前端" />
   
  <meta name="description" content="LIEFox一个有趣又好玩的学习编程网站" />
  
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title>
    JavaScript基础 |  LIEFox
  </title>
  <meta name="generator" content="hexo-theme-ayer">
  
  <link rel="shortcut icon" href="/favicon.ico" />
  
  
<link rel="stylesheet" href="/dist/main.css">

  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css">

  
<link rel="stylesheet" href="/css/custom.css">

  
  
<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>

  
  

  
<script>
var _hmt = _hmt || [];
(function() {
	var hm = document.createElement("script");
	hm.src = "https://hm.baidu.com/hm.js?70837313b75a2b48b1e427bcabe5c0d9";
	var s = document.getElementsByTagName("script")[0]; 
	s.parentNode.insertBefore(hm, s);
})();
</script>



<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>

<!-- 封面标闪烁 -->
<link rel="stylesheet" href="/css/zhyBlogTitle.css">

<!-- Highlight.js -->
<link href="https://cdn.bootcdn.net/ajax/libs/highlight.js/9.18.1/styles/a11y-dark.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

</head>

</html>

<body>
  <div id="app">
    
      
      <canvas width="1777" height="841"
        style="position: fixed; left: 0px; top: 0px; z-index: 99999; pointer-events: none;"></canvas>
      
    <main class="content on">
      <section class="outer">
  <article
  id="post-JavaScript基础"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  JavaScript基础
</h1>
 

    </header>
     
    <div class="article-meta">
      <a href="/posts/a9ba4134.html" class="article-date">
  <time datetime="2021-03-19T16:00:00.000Z" itemprop="datePublished">2021-03-20</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E5%89%8D%E7%AB%AF%E7%AC%94%E8%AE%B0/">前端笔记</a>
  </div>
  
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> 字数统计:</span>
            <span class="post-count">16.9k</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> 阅读时长≈</span>
            <span class="post-count">70 分钟</span>
        </span>
    </span>
</div>
 
    </div>
      
    <div class="tocbot"></div>




  
    <div class="article-entry" itemprop="articleBody">
       
  <p><img src="https://i.loli.net/2021/03/19/2foRsgcP4vxdTnH.png" alt="image-20210319220813163"></p>
<a id="more"></a>

<h1 id="JavaScript基础"><a href="#JavaScript基础" class="headerlink" title="JavaScript基础"></a>JavaScript基础</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>JavaScript是世界上最流行的脚本语言，因为你在电脑、手机、平板上浏览的所有的网页，以及无数基于HTML5的手机App，交互逻辑都是由JavaScript驱动的。</p>
<p>简单地说，JavaScript是一种运行在浏览器中的解释型的编程语言。</p>
<p>那么问题来了，为什么我们要学JavaScript？尤其是当你已经掌握了某些其他编程语言如Java、C++的情况下。</p>
<p>简单粗暴的回答就是：因为你没有选择。在Web世界里，只有JavaScript能跨平台、跨浏览器驱动网页，与用户交互。</p>
<p>Flash背后的ActionScript曾经流行过一阵子，不过随着移动应用的兴起，没有人用Flash开发手机App，所以它目前已经边缘化了。相反，随着HTML5在PC和移动端越来越流行，JavaScript变得更加重要了。并且，新兴的Node.js把JavaScript引入到了服务器端，JavaScript已经变成了全能型选手。</p>
<p>JavaScript一度被认为是一种玩具编程语言，它有很多缺陷，所以不被大多数后端开发人员所重视。很多人认为，写JavaScript代码很简单，并且JavaScript只是为了在网页上添加一点交互和动画效果。</p>
<p>但这是完全错误的理解。JavaScript确实很容易上手，但其精髓却不为大多数开发人员所熟知。编写高质量的JavaScript代码更是难上加难。</p>
<p>一个合格的开发人员应该精通JavaScript和其他编程语言。如果你已经掌握了其他编程语言，或者你还什么都不会，请立刻开始学习JavaScript，不要被Web时代所淘汰。</p>
<h3 id="JavaScript历史"><a href="#JavaScript历史" class="headerlink" title="JavaScript历史"></a>JavaScript历史</h3><p>要了解JavaScript，我们首先要回顾一下JavaScript的诞生。</p>
<p>在上个世纪的1995年，当时的网景公司正凭借其Navigator浏览器成为Web时代开启时最著名的第一代互联网公司。</p>
<p>由于网景公司希望能在静态HTML页面上添加一些动态效果，于是叫Brendan Eich这哥们在两周之内设计出了JavaScript语言。你没看错，这哥们只用了10天时间。</p>
<p>为什么起名叫JavaScript？原因是当时Java语言非常红火，所以网景公司希望借Java的名气来推广，但事实上JavaScript除了语法上有点像Java，其他部分基本上没啥关系。</p>
<h3 id="ECMAScript"><a href="#ECMAScript" class="headerlink" title="ECMAScript"></a>ECMAScript</h3><p>因为网景开发了JavaScript，一年后微软又模仿JavaScript开发了JScript，为了让JavaScript成为全球标准，几个公司联合ECMA（European Computer Manufacturers Association）组织定制了JavaScript语言的标准，被称为ECMAScript标准。</p>
<p>所以简单说来就是，ECMAScript是一种语言标准，而JavaScript是网景公司对ECMAScript标准的一种实现。</p>
<p>那为什么不直接把JavaScript定为标准呢？因为JavaScript是网景的注册商标。</p>
<p>不过大多数时候，我们还是用JavaScript这个词。如果你遇到ECMAScript这个词，简单把它替换为JavaScript就行了。</p>
<h3 id="JavaScript版本"><a href="#JavaScript版本" class="headerlink" title="JavaScript版本"></a>JavaScript版本</h3><p>JavaScript语言是在10天时间内设计出来的，虽然语言的设计者水平非常NB，但谁也架不住“时间紧，任务重”，所以，JavaScript有很多设计缺陷，我们后面会慢慢讲到。</p>
<p>此外，由于JavaScript的标准——ECMAScript在不断发展，最新版ECMAScript 6标准（简称ES6）已经在2015年6月正式发布了，所以，讲到JavaScript的版本，实际上就是说它实现了ECMAScript标准的哪个版本。</p>
<p>由于浏览器在发布时就确定了JavaScript的版本，加上很多用户还在使用IE6这种古老的浏览器，这就导致你在写JavaScript的时候，要照顾一下老用户，不能一上来就用最新的ES6标准写，否则，老用户的浏览器是无法运行新版本的JavaScript代码的。</p>
<h2 id="快速入门"><a href="#快速入门" class="headerlink" title="快速入门"></a>快速入门</h2><h3 id="第一个JavaScript程序"><a href="#第一个JavaScript程序" class="headerlink" title="第一个JavaScript程序"></a>第一个JavaScript程序</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">title</span>&gt;</span><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">			alert(<span class="string">&quot;hello world&quot;</span>)</span></span><br><span class="line">		<span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="https://i.loli.net/2021/03/20/Sba5yzYrUmsElJN.png" alt="image-20210320105924982"></p>
<h3 id="JavaScript有两种方法引入"><a href="#JavaScript有两种方法引入" class="headerlink" title="JavaScript有两种方法引入"></a>JavaScript有两种方法引入</h3><ul>
<li><p>一种是上面那种</p>
</li>
<li><p>一种是新建一个js文件来引入</p>
<p>hello world.html</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">title</span>&gt;</span><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;helloworld.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>hello world.js</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">alert</span><span class="params">(<span class="string">&quot;你好，JavaScript&quot;</span>)</span></span></span><br></pre></td></tr></table></figure>

<p><img src="https://i.loli.net/2021/03/20/zONWSJj8CZX4rfB.png" alt="image-20210320110252260"></p>
<p><code>注意：链入式的JavaScript建议与需要链入的html名字一致，来保证羡慕的清楚</code></p>
</li>
</ul>
<h3 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h3><p>以<code>//</code>开头直到行末的字符被视为行注释，注释是给开发人员看到，JavaScript引擎会自动忽略：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="regexp">//</span> 这是一行注释</span><br><span class="line">alert(<span class="string">&#x27;hello&#x27;</span>); <span class="regexp">//</span> 这也是注释</span><br></pre></td></tr></table></figure>

<p>另一种块注释是用<code>/*...*/</code>把多行字符包裹起来，把一大“块”视为一个注释：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 从这里开始是块注释</span></span><br><span class="line"><span class="comment">仍然是注释</span></span><br><span class="line"><span class="comment">仍然是注释</span></span><br><span class="line"><span class="comment">注释结束 */</span></span><br></pre></td></tr></table></figure>

<h3 id="JavaScript定义变量"><a href="#JavaScript定义变量" class="headerlink" title="JavaScript定义变量"></a>JavaScript定义变量</h3><figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//定义变量 	var 变量名 = 变量值</span></span><br><span class="line"><span class="keyword">var</span> <span class="symbol">score</span> = <span class="number">89</span>;</span><br></pre></td></tr></table></figure>

<h3 id="JavaScript条件控制"><a href="#JavaScript条件控制" class="headerlink" title="JavaScript条件控制"></a>JavaScript条件控制</h3><figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="symbol">score</span> = <span class="number">89</span>;</span><br><span class="line"><span class="keyword">if</span> (<span class="symbol">score</span> &gt; <span class="number">90</span> &amp;&amp; <span class="symbol">score</span> &lt; <span class="number">100</span>) &#123;</span><br><span class="line">	alert(<span class="string">&quot;优秀&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="symbol">score</span> &gt; <span class="number">80</span> &amp;&amp; <span class="symbol">score</span> &lt; <span class="number">90</span>) &#123;</span><br><span class="line">	alert(<span class="string">&quot;良好&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span>&#123;</span><br><span class="line">	alert(<span class="string">&quot;加油&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>浏览器弹出</p>
<p><img src="https://i.loli.net/2021/03/20/FUMuI5rRlBEetbh.png" alt="image-20210320210645054"></p>
<h3 id="浏览器里调试JavaScript代码"><a href="#浏览器里调试JavaScript代码" class="headerlink" title="浏览器里调试JavaScript代码"></a>浏览器里调试JavaScript代码</h3><h4 id="在浏览器里的console也可以调试JavaScrip代码甚至还可编写"><a href="#在浏览器里的console也可以调试JavaScrip代码甚至还可编写" class="headerlink" title="在浏览器里的console也可以调试JavaScrip代码甚至还可编写"></a>在浏览器里的console也可以调试JavaScrip代码甚至还可编写</h4><p><img src="https://i.loli.net/2021/03/20/TzAjELfJOM8ku3m.png" alt="image-20210320211346855"></p>
<p><code>console.log()</code>用来在控制台打印结果的。</p>
<h4 id="Sources断点调试"><a href="#Sources断点调试" class="headerlink" title="Sources断点调试"></a>Sources断点调试</h4><p><img src="https://i.loli.net/2021/03/20/fJ2QWlXBRsS9wMU.png" alt="image-20210320211755469"></p>
<h3 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h3><p>计算机顾名思义就是可以做数学计算的机器，因此，计算机程序理所当然地可以处理各种数值。但是，计算机能处理的远不止数值，还可以处理文本、图形、音频、视频、网页等各种各样的数据，不同的数据，需要定义不同的数据类型。在JavaScript中定义了以下几种数据类型：</p>
<h4 id="Number"><a href="#Number" class="headerlink" title="Number"></a>Number</h4><p>JavaScript不区分整数和浮点数，统一用Number表示，以下都是合法的Number类型：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">123</span>; <span class="regexp">//</span> 整数<span class="number">123</span></span><br><span class="line"><span class="number">0.456</span>; <span class="regexp">//</span> 浮点数<span class="number">0.456</span></span><br><span class="line"><span class="number">1.2345</span>e3; <span class="regexp">//</span> 科学计数法表示<span class="number">1.2345</span>x1000，等同于<span class="number">1234.5</span></span><br><span class="line">-<span class="number">99</span>; <span class="regexp">//</span> 负数</span><br><span class="line">NaN; <span class="regexp">//</span> NaN表示Not a Number，当无法计算结果时用NaN表示</span><br><span class="line">Infinity; <span class="regexp">//</span> Infinity表示无限大，当数值超过了JavaScript的Number所能表示的最大值时，就表示为Infinity</span><br></pre></td></tr></table></figure>

<p>计算机由于使用二进制，所以，有时候用十六进制表示整数比较方便，十六进制用0x前缀和0-9，a-f表示，例如：<code>0xff00</code>，<code>0xa5b4c3d2</code>，等等，它们和十进制表示的数值完全一样。</p>
<p>Number可以直接做四则运算，规则和数学一致：</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> + <span class="number">2</span>; <span class="comment">// 3</span></span><br><span class="line"><span class="comment">(1 + 2)</span> * <span class="number">5</span> / <span class="number">2</span>; <span class="comment">// 7.5</span></span><br><span class="line"><span class="number">2</span> / <span class="number">0</span>; <span class="comment">// Infinity</span></span><br><span class="line"><span class="number">0</span> / <span class="number">0</span>; <span class="comment">// NaN</span></span><br><span class="line"><span class="number">10</span> <span class="meta">%</span> <span class="number">3</span>; <span class="comment">// 1</span></span><br><span class="line"><span class="number">10.5</span> <span class="meta">%</span> <span class="number">3</span>; <span class="comment">// 1.5</span></span><br></pre></td></tr></table></figure>

<p>注意<code>%</code>是求余运算。</p>
<h4 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h4><p>字符串是以单引号’或双引号”括起来的任意文本，比如<code>&#39;abc&#39;</code>，<code>&quot;xyz&quot;</code>等等。请注意，<code>&#39;&#39;</code>或<code>&quot;&quot;</code>本身只是一种表示方式，不是字符串的一部分，因此，字符串<code>&#39;abc&#39;</code>只有<code>a</code>，<code>b</code>，<code>c</code>这3个字符。</p>
<h4 id="布尔值"><a href="#布尔值" class="headerlink" title="布尔值"></a>布尔值</h4><p>布尔值和布尔代数的表示完全一致，一个布尔值只有<code>true</code>、<code>false</code>两种值，要么是<code>true</code>，要么是<code>false</code>，可以直接用<code>true</code>、<code>false</code>表示布尔值，也可以通过布尔运算计算出来：</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">true</span>; <span class="regexp">//</span> 这是一个<span class="keyword">true</span>值</span><br><span class="line"><span class="keyword">false</span>; <span class="regexp">//</span> 这是一个<span class="keyword">false</span>值</span><br><span class="line"><span class="number">2</span> &gt; <span class="number">1</span>; <span class="regexp">//</span> 这是一个<span class="keyword">true</span>值</span><br><span class="line"><span class="number">2</span> &gt;= <span class="number">3</span>; <span class="regexp">//</span> 这是一个<span class="keyword">false</span>值</span><br></pre></td></tr></table></figure>

<p><code>&amp;&amp;</code>运算是与运算，只有所有都为<code>true</code>，<code>&amp;&amp;</code>运算结果才是<code>true</code>：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">true</span> <span class="string">&amp;&amp;</span> <span class="literal">true</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个&amp;&amp;语句计算结果为true</span></span><br><span class="line"><span class="literal">true</span> <span class="string">&amp;&amp;</span> <span class="literal">false</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个&amp;&amp;语句计算结果为false</span></span><br><span class="line"><span class="literal">false</span> <span class="string">&amp;&amp;</span> <span class="literal">true</span> <span class="string">&amp;&amp;</span> <span class="literal">false</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个&amp;&amp;语句计算结果为false</span></span><br></pre></td></tr></table></figure>

<p><code>||</code>运算是或运算，只要其中有一个为<code>true</code>，<code>||</code>运算结果就是<code>true</code>：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">false</span> <span class="string">||</span> <span class="literal">false</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个||语句计算结果为false</span></span><br><span class="line"><span class="literal">true</span> <span class="string">||</span> <span class="literal">false</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个||语句计算结果为true</span></span><br><span class="line"><span class="literal">false</span> <span class="string">||</span> <span class="literal">true</span> <span class="string">||</span> <span class="literal">false</span><span class="string">;</span> <span class="string">//</span> <span class="string">这个||语句计算结果为true</span></span><br></pre></td></tr></table></figure>

<p><code>!</code>运算是非运算，它是一个单目运算符，把<code>true</code>变成<code>false</code>，<code>false</code>变成<code>true</code>：</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">! <span class="keyword">true</span>; <span class="regexp">//</span> 结果为<span class="keyword">false</span></span><br><span class="line">! <span class="keyword">false</span>; <span class="regexp">//</span> 结果为<span class="keyword">true</span></span><br><span class="line">! (<span class="number">2</span> &gt; <span class="number">5</span>); <span class="regexp">//</span> 结果为<span class="keyword">true</span></span><br></pre></td></tr></table></figure>

<p>布尔值经常用在条件判断中，比如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> age = <span class="number">15</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123;</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="比较运算符"><a href="#比较运算符" class="headerlink" title="比较运算符"></a>比较运算符</h3><p>当我们对Number做比较时，可以通过比较运算符得到一个布尔值：</p>
<figure class="highlight basic"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">2 </span>&gt; <span class="number">5</span>; // false</span><br><span class="line"><span class="symbol">5 </span>&gt;= <span class="number">2</span>; // true</span><br><span class="line"><span class="symbol">7 </span>== <span class="number">7</span>; // true</span><br></pre></td></tr></table></figure>

<p>实际上，JavaScript允许对任意数据类型做比较：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">false</span> <span class="string">==</span> <span class="number">0</span><span class="string">;</span> <span class="string">//</span> <span class="literal">true</span></span><br><span class="line"><span class="literal">false</span> <span class="string">===</span> <span class="number">0</span><span class="string">;</span> <span class="string">//</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure>

<p>要特别注意相等运算符<code>==</code>。JavaScript在设计时，有两种比较运算符：</p>
<p>第一种是<code>==</code>比较，它会自动转换数据类型再比较，很多时候，会得到非常诡异的结果；</p>
<p>第二种是<code>===</code>比较，它不会自动转换数据类型，如果数据类型不一致，返回<code>false</code>，如果一致，再比较。</p>
<p>由于JavaScript这个设计缺陷，<em>不要</em>使用<code>==</code>比较，始终坚持使用<code>===</code>比较。</p>
<p>另一个例外是<code>NaN</code>这个特殊的Number与所有其他值都不相等，包括它自己：</p>
<figure class="highlight arcade"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">NaN</span> === <span class="literal">NaN</span>; <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>唯一能判断<code>NaN</code>的方法是通过<code>isNaN()</code>函数：</p>
<figure class="highlight coffeescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">isNaN</span>(<span class="literal">NaN</span>); <span class="regexp">//</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure>

<p>最后要注意浮点数的相等比较：</p>
<figure class="highlight basic"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">1 </span>/ <span class="number">3</span> === (<span class="number">1</span> - <span class="number">2</span> / <span class="number">3</span>); // false</span><br></pre></td></tr></table></figure>

<p>这不是JavaScript的设计缺陷。浮点数在运算过程中会产生误差，因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等，只能计算它们之差的绝对值，看是否小于某个阈值：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">Math</span>.abs(<span class="number">1</span> / <span class="number">3</span> - (<span class="number">1</span> - <span class="number">2</span> / <span class="number">3</span>)) &lt; <span class="number">0</span>.<span class="number">0000001</span>; // true</span><br></pre></td></tr></table></figure>

<h4 id="null和undefined"><a href="#null和undefined" class="headerlink" title="null和undefined"></a>null和undefined</h4><p><code>null</code>表示一个“空”的值，它和<code>0</code>以及空字符串<code>&#39;&#39;</code>不同，<code>0</code>是一个数值，<code>&#39;&#39;</code>表示长度为0的字符串，而<code>null</code>表示“空”。</p>
<p>在其他语言中，也有类似JavaScript的<code>null</code>的表示，例如Java也用<code>null</code>，Swift用<code>nil</code>，Python用<code>None</code>表示。但是，在JavaScript中，还有一个和<code>null</code>类似的<code>undefined</code>，它表示“未定义”。</p>
<p>JavaScript的设计者希望用<code>null</code>表示一个空的值，而<code>undefined</code>表示值未定义。事实证明，这并没有什么卵用，区分两者的意义不大。大多数情况下，我们都应该用<code>null</code>。<code>undefined</code>仅仅在判断函数参数是否传递的情况下有用。</p>
<h4 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h4><p>数组是一组按顺序排列的集合，集合的每个值称为元素。JavaScript的数组可以包括任意数据类型。例如：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3.14</span>, <span class="string">&#x27;Hello&#x27;</span>, <span class="literal">null</span>, <span class="literal">true</span>]<span class="string">;</span></span><br></pre></td></tr></table></figure>

<p>上述数组包含6个元素。数组用<code>[]</code>表示，元素之间用<code>,</code>分隔。</p>
<p>另一种创建数组的方法是通过<code>Array()</code>函数实现：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">new</span> Array(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>); // 创建了数组[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br></pre></td></tr></table></figure>

<p>然而，出于代码的可读性考虑，强烈建议直接使用<code>[]</code>。</p>
<p>数组的元素可以通过索引来访问。请注意，索引的起始值为<code>0</code>：</p>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3.14</span>, <span class="string">&#x27;Hello&#x27;</span>, null, <span class="literal">true</span>];</span><br><span class="line">arr[<span class="number">0</span>]; <span class="regexp">//</span> 返回索引为<span class="number">0</span>的元素，即<span class="number">1</span></span><br><span class="line">arr[<span class="number">5</span>]; <span class="regexp">//</span> 返回索引为<span class="number">5</span>的元素，即<span class="literal">true</span></span><br><span class="line">arr[<span class="number">6</span>]; <span class="regexp">//</span> 索引超出了范围，返回un<span class="function"><span class="keyword">def</span><span class="title">ined</span></span></span><br></pre></td></tr></table></figure>

<h4 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h4><p>JavaScript的对象是一组由键-值组成的无序集合，例如：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">var</span> <span class="string">person</span> <span class="string">=</span> &#123;</span><br><span class="line">    <span class="attr">name:</span> <span class="string">&#x27;Bob&#x27;</span>,</span><br><span class="line">    <span class="attr">age:</span> <span class="number">20</span>,</span><br><span class="line">    <span class="attr">tags:</span> [<span class="string">&#x27;js&#x27;</span>, <span class="string">&#x27;web&#x27;</span>, <span class="string">&#x27;mobile&#x27;</span>],</span><br><span class="line">    <span class="attr">city:</span> <span class="string">&#x27;Beijing&#x27;</span>,</span><br><span class="line">    <span class="attr">hasCar:</span> <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">zipcode:</span> <span class="literal">null</span></span><br><span class="line">&#125;<span class="string">;</span></span><br></pre></td></tr></table></figure>

<p>JavaScript对象的键都是字符串类型，值可以是任意数据类型。上述<code>person</code>对象一共定义了6个键值对，其中每个键又称为对象的属性，例如，<code>person</code>的<code>name</code>属性为<code>&#39;Bob&#39;</code>，<code>zipcode</code>属性为<code>null</code>。</p>
<p>要获取一个对象的属性，我们用<code>对象变量.属性名</code>的方式：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">person.name; <span class="regexp">//</span> <span class="string">&#x27;Bob&#x27;</span></span><br><span class="line">person.zipcode; <span class="regexp">//</span> null</span><br></pre></td></tr></table></figure>

<h3 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h3><p>变量的概念基本上和初中代数的方程变量是一致的，只是在计算机程序中，变量不仅可以是数字，还可以是任意数据类型。</p>
<p>变量在JavaScript中就是用一个变量名表示，变量名是大小写英文、数字、<code>$</code>和<code>_</code>的组合，且不能用数字开头。变量名也不能是JavaScript的关键字，如<code>if</code>、<code>while</code>等。申明一个变量用<code>var</code>语句，比如：</p>
<figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">var</span> a; <span class="comment">// 申明了变量a，此时a的值为undefined</span></span><br><span class="line"><span class="built_in">var</span> $b = <span class="number">1</span>; <span class="comment">// 申明了变量$b，同时给$b赋值，此时$b的值为1</span></span><br><span class="line"><span class="built_in">var</span> s_007 = <span class="string">&#x27;007&#x27;</span>; <span class="comment">// s_007是一个字符串</span></span><br><span class="line"><span class="built_in">var</span> Answer = <span class="literal">true</span>; <span class="comment">// Answer是一个布尔值true</span></span><br><span class="line"><span class="built_in">var</span> t = <span class="built_in">null</span>; <span class="comment">// t的值是null</span></span><br></pre></td></tr></table></figure>

<p>变量名也可以用中文，但是，请不要给自己找麻烦。</p>
<p>在JavaScript中，使用等号<code>=</code>对变量进行赋值。可以把任意数据类型赋值给变量，同一个变量可以反复赋值，而且可以是不同类型的变量，但是要注意只能用<code>var</code>申明一次，例如：</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var <span class="keyword">a</span> = <span class="number">123</span>;<span class="comment"> // a的值是整数123</span></span><br><span class="line"><span class="keyword">a</span> = <span class="string">&#x27;ABC&#x27;</span>;<span class="comment"> // a变为字符串</span></span><br></pre></td></tr></table></figure>

<p>这种变量本身类型不固定的语言称之为动态语言，与之对应的是静态语言。静态语言在定义变量时必须指定变量类型，如果赋值的时候类型不匹配，就会报错。例如Java是静态语言，赋值语句如下：</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">int <span class="keyword">a</span> = <span class="number">123</span>;<span class="comment"> // a是整数类型变量，类型用int申明</span></span><br><span class="line"><span class="keyword">a</span> = <span class="string">&quot;ABC&quot;</span>;<span class="comment"> // 错误：不能把字符串赋给整型变量</span></span><br></pre></td></tr></table></figure>

<p>和静态语言相比，动态语言更灵活，就是这个原因。</p>
<p>请不要把赋值语句的等号等同于数学的等号。比如下面的代码：</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var x</span> = 10;</span><br><span class="line"><span class="attribute">x</span> = x + 2;</span><br></pre></td></tr></table></figure>

<p>如果从数学上理解<code>x = x + 2</code>那无论如何是不成立的，在程序中，赋值语句先计算右侧的表达式<code>x + 2</code>，得到结果<code>12</code>，再赋给变量<code>x</code>。由于<code>x</code>之前的值是<code>10</code>，重新赋值后，<code>x</code>的值变成<code>12</code>。</p>
<h3 id="严格检查模式"><a href="#严格检查模式" class="headerlink" title="严格检查模式"></a>严格检查模式</h3><p>JavaScript在设计之初，为了方便初学者学习，并不强制要求用<code>var</code>申明变量。这个设计错误带来了严重的后果：如果一个变量没有通过<code>var</code>申明就被使用，那么该变量就自动被申明为全局变量：</p>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">i</span> = <span class="number">10</span><span class="comment">; // i现在是全局变量</span></span><br></pre></td></tr></table></figure>

<p>在同一个页面的不同的JavaScript文件中，如果都不用<code>var</code>申明，恰好都使用了变量<code>i</code>，将造成变量<code>i</code>互相影响，产生难以调试的错误结果。</p>
<p>使用<code>var</code>申明的变量则不是全局变量，它的范围被限制在该变量被申明的函数体内（函数的概念将稍后讲解），同名变量在不同的函数体内互不冲突。</p>
<p>为了修补JavaScript这一严重设计缺陷，ECMA在后续规范中推出了strict模式，在strict模式下运行的JavaScript代码，强制通过<code>var</code>申明变量，未使用<code>var</code>申明变量就使用的，将导致运行错误。</p>
<p>启用strict模式的方法是在JavaScript代码的第一行写上：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br></pre></td></tr></table></figure>

<p>这是一个字符串，不支持strict模式的浏览器会把它当做一个字符串语句执行，支持strict模式的浏览器将开启strict模式运行JavaScript</p>
<p><img src="https://i.loli.net/2021/03/21/8DThUArekREJc6v.png" alt="image-20210321001011534"></p>
<h3 id="字符串-1"><a href="#字符串-1" class="headerlink" title="字符串"></a>字符串</h3><p>JavaScript的字符串就是用<code>&#39;&#39;</code>或<code>&quot;&quot;</code>括起来的字符表示。</p>
<p>如果<code>&#39;</code>本身也是一个字符，那就可以用<code>&quot;&quot;</code>括起来，比如<code>&quot;I&#39;m OK&quot;</code>包含的字符是<code>I</code>，<code>&#39;</code>，<code>m</code>，空格，<code>O</code>，<code>K</code>这6个字符。</p>
<p>如果字符串内部既包含<code>&#39;</code>又包含<code>&quot;</code>怎么办？可以用转义字符<code>\</code>来标识，比如：</p>
<figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">&#x27;I</span>\<span class="symbol">&#x27;m</span> \<span class="string">&quot;OK\&quot;</span>!&#x27;;</span><br></pre></td></tr></table></figure>

<p>表示的字符串内容是：<code>I&#39;m &quot;OK&quot;!</code></p>
<p>转义字符<code>\</code>可以转义很多字符，比如<code>\n</code>表示换行，<code>\t</code>表示制表符，字符<code>\</code>本身也要转义，所以<code>\\</code>表示的字符就是<code>\</code>。</p>
<p>ASCII字符可以以<code>\x##</code>形式的十六进制表示，例如：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;\x41&#x27;</span>; <span class="regexp">//</span> 完全等同于 <span class="string">&#x27;A&#x27;</span></span><br></pre></td></tr></table></figure>

<p>还可以用<code>\u####</code>表示一个Unicode字符：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;\u4e2d\u6587&#x27;</span>; <span class="regexp">//</span> 完全等同于 <span class="string">&#x27;中文&#x27;</span></span><br></pre></td></tr></table></figure>

<h4 id="多行字符串"><a href="#多行字符串" class="headerlink" title="多行字符串"></a>多行字符串</h4><p>由于多行字符串用<code>\n</code>写起来比较费事，所以最新的ES6标准新增了一种多行字符串的表示方法，用反引号 <em><code>\* ... \*</code></em> 表示：</p>
<figure class="highlight autohotkey"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">`这是一个</span><br><span class="line">多行</span><br><span class="line">字符串`;</span><br></pre></td></tr></table></figure>

<p><em>注意</em>：反引号在键盘的ESC下方，数字键1的左边：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">┌─────┐ ┌─────┬─────┬─────┬─────┐</span><br><span class="line">│ ESC │ │ F1  │ F2  │ F3  │ F4  │</span><br><span class="line">│     │ │     │     │     │     │</span><br><span class="line">└─────┘ └─────┴─────┴─────┴─────┘</span><br><span class="line">┌─────┬─────┬─────┬─────┬─────┐</span><br><span class="line">│  ~  │  !  │  @  │  #  │  $  │</span><br><span class="line">│  &#96;  │  1  │  2  │  3  │  4  │</span><br><span class="line">├─────┴──┬──┴──┬──┴──┬──┴──┬──┘</span><br><span class="line">│        │     │     │     │</span><br><span class="line">│  tab   │  Q  │  W  │  E  │</span><br><span class="line">├────────┴──┬──┴──┬──┴──┬──┘</span><br><span class="line">│           │     │     │</span><br><span class="line">│ caps lock │  A  │  S  │</span><br><span class="line">└───────────┴─────┴─────┘</span><br></pre></td></tr></table></figure>

<p>练习：测试你的浏览器是否支持ES6标准，如果不支持，请把多行字符串用<code>\n</code>重新表示出来：</p>
<p><img src="https://i.loli.net/2021/03/21/wEC5knmc7big3St.png" alt="image-20210321002051023"></p>
<h4 id="模板字符串"><a href="#模板字符串" class="headerlink" title="模板字符串"></a>模板字符串</h4><p>要把多个字符串连接起来，可以用<code>+</code>号连接：</p>
<figure class="highlight delphi"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="keyword">name</span> = <span class="string">&#x27;小明&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">var</span> <span class="keyword">message</span> = <span class="string">&#x27;你好, &#x27;</span> + <span class="keyword">name</span> + <span class="string">&#x27;, 你今年&#x27;</span> + age + <span class="string">&#x27;岁了!&#x27;</span>;</span><br><span class="line">alert(<span class="keyword">message</span>);</span><br></pre></td></tr></table></figure>

<p>如果有很多变量需要连接，用<code>+</code>号就比较麻烦。ES6新增了一种模板字符串，表示方法和上面的多行字符串一样，但是它会自动替换字符串中的变量：</p>
<figure class="highlight arcade"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;小明&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">var</span> message = <span class="string">`你好, <span class="subst">$&#123;name&#125;</span>, 你今年<span class="subst">$&#123;age&#125;</span>岁了!`</span>;</span><br><span class="line">alert(message);</span><br></pre></td></tr></table></figure>

<p>练习：测试你的浏览器是否支持ES6模板字符串，如果不支持，请把模板字符串改为<code>+</code>连接的普通字符串：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name=<span class="string">&quot;liefox&quot;</span></span><br><span class="line"><span class="keyword">var</span> age=<span class="string">&quot;2&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">`你好, <span class="subst">$&#123;name&#125;</span>, 你今年<span class="subst">$&#123;age&#125;</span>岁了!`</span>);</span><br></pre></td></tr></table></figure>

<p><img src="https://i.loli.net/2021/03/21/kGsPq1QSZIVluH3.png" alt="image-20210321002906551"></p>
<h4 id="操作字符串"><a href="#操作字符串" class="headerlink" title="操作字符串"></a>操作字符串</h4><p>字符串常见的操作如下：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">&#x27;Hello, world!&#x27;</span>;</span><br><span class="line">s.length; <span class="comment">// 13</span></span><br></pre></td></tr></table></figure>

<p>要获取字符串某个指定位置的字符，使用类似Array的下标操作，索引号从0开始：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;Hello, world!&#x27;</span>;</span><br><span class="line"></span><br><span class="line">s[<span class="number">0</span>]; <span class="regexp">//</span> <span class="string">&#x27;H&#x27;</span></span><br><span class="line">s[<span class="number">6</span>]; <span class="regexp">//</span> <span class="string">&#x27; &#x27;</span></span><br><span class="line">s[<span class="number">7</span>]; <span class="regexp">//</span> <span class="string">&#x27;w&#x27;</span></span><br><span class="line">s[<span class="number">12</span>]; <span class="regexp">//</span> <span class="string">&#x27;!&#x27;</span></span><br><span class="line">s[<span class="number">13</span>]; <span class="regexp">//</span> undefined 超出范围的索引不会报错，但一律返回undefined</span><br></pre></td></tr></table></figure>

<p><em>需要特别注意的是</em>，字符串是不可变的，如果对字符串的某个索引赋值，不会有任何错误，但是，也没有任何效果：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;Test&#x27;</span>;</span><br><span class="line">s[<span class="number">0</span>] = <span class="string">&#x27;X&#x27;</span>;</span><br><span class="line">alert(s); <span class="regexp">//</span> s仍然为<span class="string">&#x27;Test&#x27;</span></span><br></pre></td></tr></table></figure>

<p>JavaScript为字符串提供了一些常用方法，注意，调用这些方法本身不会改变原有字符串的内容，而是返回一个新字符串：</p>
<h4 id="toUpperCase"><a href="#toUpperCase" class="headerlink" title="toUpperCase"></a>toUpperCase</h4><p><code>toUpperCase()</code>把一个字符串全部变为大写：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;Hello&#x27;</span>;</span><br><span class="line">s.toUpperCase(); <span class="regexp">//</span> 返回<span class="string">&#x27;HELLO&#x27;</span></span><br></pre></td></tr></table></figure>

<h4 id="toLowerCase"><a href="#toLowerCase" class="headerlink" title="toLowerCase"></a>toLowerCase</h4><p><code>toLowerCase()</code>把一个字符串全部变为小写：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;Hello&#x27;</span>;</span><br><span class="line">var lower = s.toLowerCase(); <span class="regexp">//</span> 返回<span class="string">&#x27;hello&#x27;</span>并赋值给变量lower</span><br><span class="line">lower; <span class="regexp">//</span> <span class="string">&#x27;hello&#x27;</span></span><br></pre></td></tr></table></figure>

<h4 id="indexOf"><a href="#indexOf" class="headerlink" title="indexOf"></a>indexOf</h4><p><code>indexOf()</code>会搜索指定字符串出现的位置：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;hello, world&#x27;</span>;</span><br><span class="line">s.indexOf(<span class="string">&#x27;world&#x27;</span>); <span class="regexp">//</span> 返回<span class="number">7</span></span><br><span class="line">s.indexOf(<span class="string">&#x27;World&#x27;</span>); <span class="regexp">//</span> 没有找到指定的子串，返回-<span class="number">1</span></span><br></pre></td></tr></table></figure>

<h4 id="substring"><a href="#substring" class="headerlink" title="substring"></a>substring</h4><p><code>substring()</code>返回指定索引区间的子串：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> s = &#x27;hello, world&#x27;</span><br><span class="line"><span class="attribute">s</span>.substring(<span class="number">0</span>, <span class="number">5</span>); // 从索引<span class="number">0</span>开始到<span class="number">5</span>（不包括<span class="number">5</span>），返回&#x27;hello&#x27;</span><br><span class="line"><span class="attribute">s</span>.substring(<span class="number">7</span>); // 从索引<span class="number">7</span>开始到结束，返回&#x27;world&#x27;</span><br></pre></td></tr></table></figure>

<h3 id="数组-1"><a href="#数组-1" class="headerlink" title="数组"></a>数组</h3><p>JavaScript的<code>Array</code>可以包含任意数据类型，并通过索引来访问每个元素。</p>
<p>要取得<code>Array</code>的长度，直接访问<code>length</code>属性：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3.14</span>, <span class="string">&#x27;Hello&#x27;</span>, <span class="literal">null</span>, <span class="literal">true</span>];</span><br><span class="line">arr.length; <span class="comment">// 6</span></span><br></pre></td></tr></table></figure>

<p><em>请注意</em>，直接给<code>Array</code>的<code>length</code>赋一个新的值会导致<code>Array</code>大小的变化：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">arr.length; <span class="regexp">//</span> <span class="number">3</span></span><br><span class="line">arr.length = <span class="number">6</span>;</span><br><span class="line">arr; <span class="regexp">//</span> arr变为[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, undefined, undefined, undefined]</span><br><span class="line">arr.length = <span class="number">2</span>;</span><br><span class="line">arr; <span class="regexp">//</span> arr变为[<span class="number">1</span>, <span class="number">2</span>]</span><br></pre></td></tr></table></figure>

<p><code>Array</code>可以通过索引把对应的元素修改为新的值，因此，对<code>Array</code>的索引进行赋值会直接修改这个<code>Array</code>：</p>
<figure class="highlight prolog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">arr[<span class="number">1</span>] = <span class="number">99</span>;</span><br><span class="line">arr; // arr现在变为[<span class="string">&#x27;A&#x27;</span>, <span class="number">99</span>, <span class="string">&#x27;C&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p><em>请注意</em>，如果通过索引赋值时，索引超过了范围，同样会引起<code>Array</code>大小的变化：</p>
<figure class="highlight prolog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">arr[<span class="number">5</span>] = <span class="string">&#x27;x&#x27;</span>;</span><br><span class="line">arr; // arr变为[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, undefined, undefined, <span class="string">&#x27;x&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p>大多数其他编程语言不允许直接改变数组的大小，越界访问索引会报错。然而，JavaScript的<code>Array</code>却不会有任何错误。在编写代码时，不建议直接修改<code>Array</code>的大小，访问索引时要确保索引不会越界。</p>
<h4 id="indexOf-1"><a href="#indexOf-1" class="headerlink" title="indexOf"></a>indexOf</h4><p>与String类似，<code>Array</code>也可以通过<code>indexOf()</code>来搜索一个指定的元素的位置：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">10</span>, <span class="number">20</span>, <span class="string">&#x27;30&#x27;</span>, <span class="string">&#x27;xyz&#x27;</span>];</span><br><span class="line">arr.indexOf(<span class="number">10</span>); <span class="regexp">//</span> 元素<span class="number">10</span>的索引为<span class="number">0</span></span><br><span class="line">arr.indexOf(<span class="number">20</span>); <span class="regexp">//</span> 元素<span class="number">20</span>的索引为<span class="number">1</span></span><br><span class="line">arr.indexOf(<span class="number">30</span>); <span class="regexp">//</span> 元素<span class="number">30</span>没有找到，返回-<span class="number">1</span></span><br><span class="line">arr.indexOf(<span class="string">&#x27;30&#x27;</span>); <span class="regexp">//</span> 元素<span class="string">&#x27;30&#x27;</span>的索引为<span class="number">2</span></span><br></pre></td></tr></table></figure>

<p>注意了，数字<code>30</code>和字符串<code>&#39;30&#39;</code>是不同的元素。</p>
<h4 id="slice"><a href="#slice" class="headerlink" title="slice"></a>slice</h4><p><code>slice()</code>就是对应String的<code>substring()</code>版本，它截取<code>Array</code>的部分元素，然后返回一个新的<code>Array</code>：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>];</span><br><span class="line">arr.slice(<span class="number">0</span>, <span class="number">3</span>); <span class="regexp">//</span> 从索引<span class="number">0</span>开始，到索引<span class="number">3</span>结束，但不包括索引<span class="number">3</span>: [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]</span><br><span class="line">arr.slice(<span class="number">3</span>); <span class="regexp">//</span> 从索引<span class="number">3</span>开始到结束: [<span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p>注意到<code>slice()</code>的起止参数包括开始索引，不包括结束索引。</p>
<p>如果不给<code>slice()</code>传递任何参数，它就会从头到尾截取所有元素。利用这一点，我们可以很容易地复制一个<code>Array</code>：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>];</span><br><span class="line">var aCopy = arr.slice();</span><br><span class="line">aCopy; <span class="regexp">//</span> [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>]</span><br><span class="line">aCopy === arr; <span class="regexp">//</span> false</span><br></pre></td></tr></table></figure>

<h4 id="push和pop"><a href="#push和pop" class="headerlink" title="push和pop"></a>push和pop</h4><p><code>push()</code>向<code>Array</code>的末尾添加若干元素，<code>pop()</code>则把<code>Array</code>的最后一个元素删除掉：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">1</span>, <span class="number">2</span>];</span><br><span class="line">arr.push(<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>); <span class="regexp">//</span> 返回Array新的长度: <span class="number">4</span></span><br><span class="line">arr; <span class="regexp">//</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>]</span><br><span class="line">arr.pop(); <span class="regexp">//</span> pop()返回<span class="string">&#x27;B&#x27;</span></span><br><span class="line">arr; <span class="regexp">//</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="string">&#x27;A&#x27;</span>]</span><br><span class="line">arr.pop(); arr.pop(); arr.pop(); <span class="regexp">//</span> 连续pop <span class="number">3</span>次</span><br><span class="line">arr; <span class="regexp">//</span> []</span><br><span class="line">arr.pop(); <span class="regexp">//</span> 空数组继续pop不会报错，而是返回undefined</span><br><span class="line">arr; <span class="regexp">//</span> []</span><br></pre></td></tr></table></figure>

<h4 id="unshift和shift"><a href="#unshift和shift" class="headerlink" title="unshift和shift"></a>unshift和shift</h4><p>如果要往<code>Array</code>的头部添加若干元素，使用<code>unshift()</code>方法，<code>shift()</code>方法则把<code>Array</code>的第一个元素删掉：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="number">1</span>, <span class="number">2</span>];</span><br><span class="line">arr.unshift(<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>); <span class="regexp">//</span> 返回Array新的长度: <span class="number">4</span></span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line">arr.shift(); <span class="regexp">//</span> <span class="string">&#x27;A&#x27;</span></span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;B&#x27;</span>, <span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line">arr.shift(); arr.shift(); arr.shift(); <span class="regexp">//</span> 连续shift <span class="number">3</span>次</span><br><span class="line">arr; <span class="regexp">//</span> []</span><br><span class="line">arr.shift(); <span class="regexp">//</span> 空数组继续shift不会报错，而是返回undefined</span><br><span class="line">arr; <span class="regexp">//</span> []</span><br></pre></td></tr></table></figure>

<h4 id="sort"><a href="#sort" class="headerlink" title="sort"></a>sort</h4><p><code>sort()</code>可以对当前<code>Array</code>进行排序，它会直接修改当前<code>Array</code>的元素位置，直接调用时，按照默认顺序排序：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;A&#x27;</span>];</span><br><span class="line">arr.sort();</span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p>能否按照我们自己指定的顺序排序呢？完全可以，我们将在后面的函数中讲到。</p>
<h4 id="reverse"><a href="#reverse" class="headerlink" title="reverse"></a>reverse</h4><p><code>reverse()</code>把整个<code>Array</code>的元素给调个个，也就是反转：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;one&#x27;</span>, <span class="string">&#x27;two&#x27;</span>, <span class="string">&#x27;three&#x27;</span>];</span><br><span class="line">arr.reverse(); </span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;three&#x27;</span>, <span class="string">&#x27;two&#x27;</span>, <span class="string">&#x27;one&#x27;</span>]</span><br></pre></td></tr></table></figure>

<h4 id="splice"><a href="#splice" class="headerlink" title="splice"></a>splice</h4><p><code>splice()</code>方法是修改<code>Array</code>的“万能方法”，它可以从指定的索引开始删除若干元素，然后再从该位置添加若干元素：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;Microsoft&#x27;</span>, <span class="string">&#x27;Apple&#x27;</span>, <span class="string">&#x27;Yahoo&#x27;</span>, <span class="string">&#x27;AOL&#x27;</span>, <span class="string">&#x27;Excite&#x27;</span>, <span class="string">&#x27;Oracle&#x27;</span>];</span><br><span class="line"><span class="regexp">//</span> 从索引<span class="number">2</span>开始删除<span class="number">3</span>个元素,然后再添加两个元素:</span><br><span class="line">arr.splice(<span class="number">2</span>, <span class="number">3</span>, <span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Facebook&#x27;</span>); <span class="regexp">//</span> 返回删除的元素 [<span class="string">&#x27;Yahoo&#x27;</span>, <span class="string">&#x27;AOL&#x27;</span>, <span class="string">&#x27;Excite&#x27;</span>]</span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;Microsoft&#x27;</span>, <span class="string">&#x27;Apple&#x27;</span>, <span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Facebook&#x27;</span>, <span class="string">&#x27;Oracle&#x27;</span>]</span><br><span class="line"><span class="regexp">//</span> 只删除,不添加:</span><br><span class="line">arr.splice(<span class="number">2</span>, <span class="number">2</span>); <span class="regexp">//</span> [<span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Facebook&#x27;</span>]</span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;Microsoft&#x27;</span>, <span class="string">&#x27;Apple&#x27;</span>, <span class="string">&#x27;Oracle&#x27;</span>]</span><br><span class="line"><span class="regexp">//</span> 只添加,不删除:</span><br><span class="line">arr.splice(<span class="number">2</span>, <span class="number">0</span>, <span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Facebook&#x27;</span>); <span class="regexp">//</span> 返回[],因为没有删除任何元素</span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;Microsoft&#x27;</span>, <span class="string">&#x27;Apple&#x27;</span>, <span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Facebook&#x27;</span>, <span class="string">&#x27;Oracle&#x27;</span>]</span><br></pre></td></tr></table></figure>

<h4 id="concat"><a href="#concat" class="headerlink" title="concat"></a>concat</h4><p><code>concat()</code>方法把当前的<code>Array</code>和另一个<code>Array</code>连接起来，并返回一个新的<code>Array</code>：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">var added = arr.concat([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br><span class="line">added; <span class="regexp">//</span> [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">arr; <span class="regexp">//</span> [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p><em>请注意</em>，<code>concat()</code>方法并没有修改当前<code>Array</code>，而是返回了一个新的<code>Array</code>。</p>
<p>实际上，<code>concat()</code>方法可以接收任意个元素和<code>Array</code>，并且自动把<code>Array</code>拆开，然后全部添加到新的<code>Array</code>里：</p>
<figure class="highlight prolog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">arr.concat(<span class="number">1</span>, <span class="number">2</span>, [<span class="number">3</span>, <span class="number">4</span>]); // [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br></pre></td></tr></table></figure>

<h4 id="join"><a href="#join" class="headerlink" title="join"></a>join</h4><p><code>join()</code>方法是一个非常实用的方法，它把当前<code>Array</code>的每个元素都用指定的字符串连接起来，然后返回连接后的字符串：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var arr = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">arr.join(<span class="string">&#x27;-&#x27;</span>); <span class="regexp">//</span> <span class="string">&#x27;A-B-C-1-2-3&#x27;</span></span><br></pre></td></tr></table></figure>

<p>如果<code>Array</code>的元素不是字符串，将自动转换为字符串后再连接。</p>
<h4 id="多维数组"><a href="#多维数组" class="headerlink" title="多维数组"></a>多维数组</h4><p>如果数组的某个元素又是一个<code>Array</code>，则可以形成多维数组，例如：</p>
<figure class="highlight prolog"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">var arr = [[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>], [<span class="number">400</span>, <span class="number">500</span>, <span class="number">600</span>], <span class="string">&#x27;-&#x27;</span>];</span><br></pre></td></tr></table></figure>

<p>上述<code>Array</code>包含3个元素，其中头两个元素本身也是<code>Array</code>。</p>
<p>练习：如何通过索引取到<code>500</code>这个值：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>], [<span class="number">400</span>, <span class="number">500</span>, <span class="number">600</span>], <span class="string">&#x27;-&#x27;</span>];</span><br><span class="line"><span class="keyword">var</span> <span class="symbol">x</span> = arr[<span class="number">1</span>][<span class="number">1</span>];</span><br><span class="line">console.log(<span class="symbol">x</span>); <span class="comment">// x应该为500</span></span><br></pre></td></tr></table></figure>

<p><code>Array</code>提供了一种顺序存储一组元素的功能，并可以按索引来读写。</p>
<p>练习：在新生欢迎会上，你已经拿到了新同学的名单，请排序后显示：<code>欢迎XXX，XXX，XXX和XXX同学！</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="string">&#x27;小明&#x27;</span>, <span class="string">&#x27;小红&#x27;</span>, <span class="string">&#x27;大军&#x27;</span>, <span class="string">&#x27;阿黄&#x27;</span>];</span><br><span class="line">arr.sort();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">`欢迎<span class="subst">$&#123;arr[<span class="number">0</span>]&#125;</span>,<span class="subst">$&#123;arr[<span class="number">1</span>]&#125;</span>,<span class="subst">$&#123;arr[<span class="number">2</span>]&#125;</span>和<span class="subst">$&#123;arr[<span class="number">3</span>]&#125;</span>同学！`</span>);</span><br><span class="line">欢迎大军,小明,小红和阿黄同学！</span><br></pre></td></tr></table></figure>

<h3 id="对象-1"><a href="#对象-1" class="headerlink" title="对象"></a>对象</h3><p>JavaScript的对象是一种无序的集合数据类型，它由若干键值对组成。</p>
<p>JavaScript的对象用于描述现实世界中的某个对象。例如，为了描述“小明”这个淘气的小朋友，我们可以用若干键值对来描述他：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">var</span> <span class="string">xiaoming</span> <span class="string">=</span> &#123;</span><br><span class="line">    <span class="attr">name:</span> <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    <span class="attr">birth:</span> <span class="number">1990</span>,</span><br><span class="line">    <span class="attr">school:</span> <span class="string">&#x27;No.1 Middle School&#x27;</span>,</span><br><span class="line">    <span class="attr">height:</span> <span class="number">1.70</span>,</span><br><span class="line">    <span class="attr">weight:</span> <span class="number">65</span>,</span><br><span class="line">    <span class="attr">score:</span> <span class="literal">null</span></span><br><span class="line">&#125;<span class="string">;</span></span><br></pre></td></tr></table></figure>

<p>JavaScript用一个<code>&#123;...&#125;</code>表示一个对象，键值对以<code>xxx: xxx</code>形式申明，用<code>,</code>隔开。注意，最后一个键值对不需要在末尾加<code>,</code>，如果加了，有的浏览器（如低版本的IE）将报错。</p>
<p>上述对象申明了一个<code>name</code>属性，值是<code>&#39;小明&#39;</code>，<code>birth</code>属性，值是<code>1990</code>，以及其他一些属性。最后，把这个对象赋值给变量<code>xiaoming</code>后，就可以通过变量<code>xiaoming</code>来获取小明的属性了：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">xiaoming.name; <span class="regexp">//</span> <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">xiaoming.birth; <span class="regexp">//</span> <span class="number">1990</span></span><br></pre></td></tr></table></figure>

<p>访问属性是通过<code>.</code>操作符完成的，但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符，就必须用<code>&#39;&#39;</code>括起来：</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var xiaohong</span> = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小红&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;middle-school&#x27;</span>: <span class="string">&#x27;No.1 Middle School&#x27;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p><code>xiaohong</code>的属性名<code>middle-school</code>不是一个有效的变量，就需要用<code>&#39;&#39;</code>括起来。访问这个属性也无法使用<code>.</code>操作符，必须用<code>[&#39;xxx&#39;]</code>来访问：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xiaohong[<span class="string">&#x27;middle-school&#x27;</span>]; <span class="regexp">//</span> <span class="string">&#x27;No.1 Middle School&#x27;</span></span><br><span class="line">xiaohong[<span class="string">&#x27;name&#x27;</span>]; <span class="regexp">//</span> <span class="string">&#x27;小红&#x27;</span></span><br><span class="line">xiaohong.name; <span class="regexp">//</span> <span class="string">&#x27;小红&#x27;</span></span><br></pre></td></tr></table></figure>

<p>也可以用<code>xiaohong[&#39;name&#39;]</code>来访问<code>xiaohong</code>的<code>name</code>属性，不过<code>xiaohong.name</code>的写法更简洁。我们在编写JavaScript代码的时候，属性名尽量使用标准的变量名，这样就可以直接通过<code>object.prop</code>的形式访问一个属性了。</p>
<p>实际上JavaScript对象的所有属性都是字符串，不过属性对应的值可以是任意数据类型。</p>
<p>如果访问一个不存在的属性会返回什么呢？JavaScript规定，访问不存在的属性不报错，而是返回<code>undefined</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p> Run</p>
<p>小明<br>undefined</p>
<p>由于JavaScript的对象是动态类型，你可以自由地给一个对象添加或删除属性：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">var xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line">xiaoming.age; <span class="regexp">//</span> undefined</span><br><span class="line">xiaoming.age = <span class="number">18</span>; <span class="regexp">//</span> 新增一个age属性</span><br><span class="line">xiaoming.age; <span class="regexp">//</span> <span class="number">18</span></span><br><span class="line"><span class="keyword">delete</span> xiaoming.age; <span class="regexp">//</span> 删除age属性</span><br><span class="line">xiaoming.age; <span class="regexp">//</span> undefined</span><br><span class="line"><span class="keyword">delete</span> xiaoming[<span class="string">&#x27;name&#x27;</span>]; <span class="regexp">//</span> 删除name属性</span><br><span class="line">xiaoming.name; <span class="regexp">//</span> undefined</span><br><span class="line"><span class="keyword">delete</span> xiaoming.school; <span class="regexp">//</span> 删除一个不存在的school属性也不会报错</span><br></pre></td></tr></table></figure>

<p>如果我们要检测<code>xiaoming</code>是否拥有某一属性，可以用<code>in</code>操作符：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">var</span> <span class="string">xiaoming</span> <span class="string">=</span> &#123;</span><br><span class="line">    <span class="attr">name:</span> <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    <span class="attr">birth:</span> <span class="number">1990</span>,</span><br><span class="line">    <span class="attr">school:</span> <span class="string">&#x27;No.1 Middle School&#x27;</span>,</span><br><span class="line">    <span class="attr">height:</span> <span class="number">1.70</span>,</span><br><span class="line">    <span class="attr">weight:</span> <span class="number">65</span>,</span><br><span class="line">    <span class="attr">score:</span> <span class="literal">null</span></span><br><span class="line">&#125;<span class="string">;</span></span><br><span class="line"><span class="string">&#x27;name&#x27;</span> <span class="string">in</span> <span class="string">xiaoming;</span> <span class="string">//</span> <span class="literal">true</span></span><br><span class="line"><span class="string">&#x27;grade&#x27;</span> <span class="string">in</span> <span class="string">xiaoming;</span> <span class="string">//</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure>

<p>不过要小心，如果<code>in</code>判断一个属性存在，这个属性不一定是<code>xiaoming</code>的，它可能是<code>xiaoming</code>继承得到的：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;toString&#x27;</span> <span class="keyword">in</span> xiaoming; <span class="regexp">//</span> true</span><br></pre></td></tr></table></figure>

<p>因为<code>toString</code>定义在<code>object</code>对象中，而所有对象最终都会在原型链上指向<code>object</code>，所以<code>xiaoming</code>也拥有<code>toString</code>属性。</p>
<p>要判断一个属性是否是<code>xiaoming</code>自身拥有的，而不是继承得到的，可以用<code>hasOwnProperty()</code>方法：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line">xiaoming.hasOwnProperty(<span class="string">&#x27;name&#x27;</span>); <span class="regexp">//</span> true</span><br><span class="line">xiaoming.hasOwnProperty(<span class="string">&#x27;toString&#x27;</span>); <span class="regexp">//</span> false</span><br></pre></td></tr></table></figure>

<h3 id="条件判断"><a href="#条件判断" class="headerlink" title="条件判断"></a>条件判断</h3><p>JavaScript使用<code>if () &#123; ... &#125; else &#123; ... &#125;</code>来进行条件判断。例如，根据年龄显示不同内容，可以用<code>if</code>语句实现如下：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123; <span class="regexp">//</span> 如果age &gt;= <span class="number">18</span>为true，则执行<span class="keyword">if</span>语句块</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123; <span class="regexp">//</span> 否则执行<span class="keyword">else</span>语句块</span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其中<code>else</code>语句是可选的。如果语句块只包含一条语句，那么可以省略<code>&#123;&#125;</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>)</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br></pre></td></tr></table></figure>

<p>省略<code>&#123;&#125;</code>的危险之处在于，如果后来想添加一些语句，却忘了写<code>&#123;&#125;</code>，就改变了<code>if...else...</code>的语义，例如：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>)</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    console.log(<span class="string">&#x27;age &lt; 18&#x27;</span>); <span class="regexp">//</span> 添加一行日志</span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>); <span class="regexp">//</span> &lt;- 这行语句已经不在<span class="keyword">else</span>的控制范围了</span><br></pre></td></tr></table></figure>

<p>上述代码的<code>else</code>子句实际上只负责执行<code>console.log(&#39;age &lt; 18&#39;);</code>，原有的<code>alert(&#39;teenager&#39;);</code>已经不属于<code>if...else...</code>的控制范围了，它每次都会执行。</p>
<p>相反地，有<code>&#123;&#125;</code>的语句就不会出错：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123;</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;age &lt; 18&#x27;</span>);</span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这就是为什么我们建议永远都要写上<code>&#123;&#125;</code>。</p>
<h4 id="多行条件判断"><a href="#多行条件判断" class="headerlink" title="多行条件判断"></a>多行条件判断</h4><p>如果还要更细致地判断条件，可以使用多个<code>if...else...</code>的组合：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> age = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123;</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (age &gt;= <span class="number">6</span>) &#123;</span><br><span class="line">    alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    alert(<span class="string">&#x27;kid&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述多个<code>if...else...</code>的组合实际上相当于两层<code>if...else...</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> age = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123;</span><br><span class="line">    alert(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (age &gt;= <span class="number">6</span>) &#123;</span><br><span class="line">        alert(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        alert(<span class="string">&#x27;kid&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>但是我们通常把<code>else if</code>连写在一起，来增加可读性。这里的<code>else</code>略掉了<code>&#123;&#125;</code>是没有问题的，因为它只包含一个<code>if</code>语句。注意最后一个单独的<code>else</code>不要略掉<code>&#123;&#125;</code>。</p>
<p><em>请注意</em>，<code>if...else...</code>语句的执行特点是二选一，在多个<code>if...else...</code>语句中，如果某个条件成立，则后续就不再继续判断了。</p>
<p>试解释为什么下面的代码显示的是<code>teenager</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> age = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">if</span> (age &gt;= <span class="number">6</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;teenager&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (age &gt;= <span class="number">18</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;adult&#x27;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;kid&#x27;</span>);</span><br><span class="line">&#125;<span class="comment">//teenager</span></span><br></pre></td></tr></table></figure>

<p>由于<code>age</code>的值为<code>20</code>，它实际上同时满足条件<code>age &gt;= 6</code>和<code>age &gt;= 18</code>，这说明条件判断的顺序非常重要。请修复后让其显示<code>adult</code>。</p>
<p>如果<code>if</code>的条件判断语句结果不是<code>true</code>或<code>false</code>怎么办？例如：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var s = <span class="string">&#x27;123&#x27;</span>;</span><br><span class="line"><span class="keyword">if</span> (s.length) &#123; <span class="regexp">//</span> 条件计算结果为<span class="number">3</span></span><br><span class="line">    <span class="regexp">//</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>JavaScript把<code>null</code>、<code>undefined</code>、<code>0</code>、<code>NaN</code>和空字符串<code>&#39;&#39;</code>视为<code>false</code>，其他值一概视为<code>true</code>，因此上述代码条件判断的结果是<code>true</code>。</p>
<h4 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h4><p>小明身高1.75，体重80.5kg。请根据BMI公式（体重除以身高的平方）帮小明计算他的BMI指数，并根据BMI指数：</p>
<ul>
<li>低于18.5：过轻</li>
<li>18.5-25：正常</li>
<li>25-28：过重</li>
<li>28-32：肥胖</li>
<li>高于32：严重肥胖</li>
</ul>
<p>用<code>if...else...</code>判断并显示结果：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> height = <span class="built_in">parseFloat</span>(prompt(<span class="string">&#x27;请输入身高(m):&#x27;</span>));</span><br><span class="line"><span class="keyword">var</span> weight = <span class="built_in">parseFloat</span>(prompt(<span class="string">&#x27;请输入体重(kg):&#x27;</span>));</span><br><span class="line"><span class="keyword">var</span> bmi = weight/(height^<span class="number">2</span>);</span><br><span class="line">alert(bmi);</span><br><span class="line"><span class="keyword">if</span> (bmi&gt;=<span class="number">32</span>)&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&quot;严重肥胖&quot;</span>);</span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(bmi&gt;=<span class="number">28</span>&amp;&amp;bmi&lt;<span class="number">32</span>)&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&quot;肥胖&quot;</span>);</span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(bmi&gt;=<span class="number">25</span>&amp;&amp;bmi&lt;<span class="number">28</span>)&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&quot;过重&quot;</span>);</span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(bmi&gt;=<span class="number">18.5</span>&amp;&amp;bmi&lt;<span class="number">25</span>)&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&quot;正常&quot;</span>);</span><br><span class="line">&#125;<span class="keyword">else</span> &#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&quot;过轻&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="循环"><a href="#循环" class="headerlink" title="循环"></a>循环</h3><p>要计算1+2+3，我们可以直接写表达式：</p>
<figure class="highlight basic"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">1 </span>+ <span class="number">2</span> + <span class="number">3</span>; // <span class="number">6</span></span><br></pre></td></tr></table></figure>

<p>要计算1+2+3+…+10，勉强也能写出来。</p>
<p>但是，要计算1+2+3+…+10000，直接写表达式就不可能了。</p>
<p>为了让计算机能计算成千上万次的重复运算，我们就需要循环语句。</p>
<p>JavaScript的循环有两种，一种是<code>for</code>循环，通过初始条件、结束条件和递增条件来循环执行语句块：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="symbol">x</span> = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">var</span> i;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">1</span>; i&lt;=<span class="number">10000</span>; i++) &#123;</span><br><span class="line">    <span class="symbol">x</span> = <span class="symbol">x</span> + i;</span><br><span class="line">&#125;</span><br><span class="line"><span class="symbol">x</span>; <span class="comment">// 50005000</span></span><br></pre></td></tr></table></figure>

<p>让我们来分析一下<code>for</code>循环的控制条件：</p>
<ul>
<li>i=1 这是初始条件，将变量i置为1；</li>
<li>i&lt;=10000 这是判断条件，满足时就继续循环，不满足就退出循环；</li>
<li>i++ 这是每次循环后的递增条件，由于每次循环后变量i都会加1，因此它终将在若干次循环后不满足判断条件<code>i&lt;=10000</code>而退出循环。</li>
</ul>
<h4 id="练习-1"><a href="#练习-1" class="headerlink" title="练习"></a>练习</h4><p>利用<code>for</code>循环计算<code>1 * 2 * 3 * ... * 10</code>的结果：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">var <span class="meta">x</span> = 1;</span><br><span class="line">var i;</span><br><span class="line">for (i=1;i&lt;=10;i++)&#123;</span><br><span class="line">  <span class="meta">x</span>=<span class="meta">x</span><span class="comment">*i;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">if</span> (<span class="meta">x</span> === 3628800) &#123;</span><br><span class="line">    console<span class="meta">.log(</span><span class="string">&#x27;1 x 2 x 3 x ... x 10 = &#x27;</span> + <span class="meta">x</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">else</span> &#123;</span><br><span class="line">    console<span class="meta">.log(</span><span class="string">&#x27;计算错误&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">//1 <span class="meta">x</span> 2 <span class="meta">x</span> 3 <span class="meta">x</span> ... <span class="meta">x</span> 10 = 3628800</span><br></pre></td></tr></table></figure>

<p><code>for</code>循环最常用的地方是利用索引来遍历数组：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="string">&#x27;Apple&#x27;</span>, <span class="string">&#x27;Google&#x27;</span>, <span class="string">&#x27;Microsoft&#x27;</span>];</span><br><span class="line"><span class="keyword">var</span> i, <span class="symbol">x</span>;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>; i&lt;arr.length; i++) &#123;</span><br><span class="line">    <span class="symbol">x</span> = arr[i];</span><br><span class="line">    console.log(<span class="symbol">x</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>for</code>循环的3个条件都是可以省略的，如果没有退出循环的判断条件，就必须使用<code>break</code>语句退出循环，否则就是死循环：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="symbol">x</span> = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (;;) &#123; <span class="comment">// 将无限循环下去</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="symbol">x</span> &gt; <span class="number">100</span>) &#123;</span><br><span class="line">        <span class="keyword">break</span>; <span class="comment">// 通过if判断来退出循环</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="symbol">x</span> ++;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="for-…-in"><a href="#for-…-in" class="headerlink" title="for … in"></a>for … in</h4><p><code>for</code>循环的一个变体是<code>for ... in</code>循环，它可以把一个对象的所有属性依次循环出来：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">var o = &#123;</span><br><span class="line">    name: <span class="string">&#x27;Jack&#x27;</span>,</span><br><span class="line">    age: 20,</span><br><span class="line">    city: <span class="string">&#x27;Beijing&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line">for (var <span class="meta">key</span> <span class="meta">in</span> o) &#123;</span><br><span class="line">    console<span class="meta">.log(</span><span class="meta">key</span>); // <span class="string">&#x27;name&#x27;</span>, <span class="string">&#x27;age&#x27;</span>, <span class="string">&#x27;city&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>要过滤掉对象继承的属性，用<code>hasOwnProperty()</code>来实现：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">var o = &#123;</span><br><span class="line">    name: <span class="string">&#x27;Jack&#x27;</span>,</span><br><span class="line">    age: 20,</span><br><span class="line">    city: <span class="string">&#x27;Beijing&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line">for (var <span class="meta">key</span> <span class="meta">in</span> o) &#123;</span><br><span class="line">    <span class="meta">if</span> (o.hasOwnProperty(<span class="meta">key</span>)) &#123;</span><br><span class="line">        console<span class="meta">.log(</span><span class="meta">key</span>); // <span class="string">&#x27;name&#x27;</span>, <span class="string">&#x27;age&#x27;</span>, <span class="string">&#x27;city&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由于<code>Array</code>也是对象，而它的每个元素的索引被视为对象的属性，因此，<code>for ... in</code>循环可以直接循环出<code>Array</code>的索引：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line"><span class="keyword">for</span> (var i <span class="keyword">in</span> a) &#123;</span><br><span class="line">    console.log(i); <span class="regexp">//</span> <span class="string">&#x27;0&#x27;</span>, <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span></span><br><span class="line">    console.log(a[i]); <span class="regexp">//</span> <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>请注意</em>，<code>for ... in</code>对<code>Array</code>的循环得到的是<code>String</code>而不是<code>Number</code>。</p>
<h4 id="while"><a href="#while" class="headerlink" title="while"></a>while</h4><p><code>for</code>循环在已知循环的初始和结束条件时非常有用。而上述忽略了条件的<code>for</code>循环容易让人看不清循环的逻辑，此时用<code>while</code>循环更佳。</p>
<p><code>while</code>循环只有一个判断条件，条件满足，就不断循环，条件不满足时则退出循环。比如我们要计算100以内所有奇数之和，可以用while循环实现：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="symbol">x</span> = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">var</span> n = <span class="number">99</span>;</span><br><span class="line"><span class="keyword">while</span> (n &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="symbol">x</span> = <span class="symbol">x</span> + n;</span><br><span class="line">    n = n - <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="symbol">x</span>; <span class="comment">// 2500</span></span><br></pre></td></tr></table></figure>

<p>在循环内部变量<code>n</code>不断自减，直到变为<code>-1</code>时，不再满足<code>while</code>条件，循环退出。</p>
<h4 id="do-…-while"><a href="#do-…-while" class="headerlink" title="do … while"></a>do … while</h4><p>最后一种循环是<code>do &#123; ... &#125; while()</code>循环，它和<code>while</code>循环的唯一区别在于，不是在每次循环开始的时候判断条件，而是在每次循环完成的时候判断条件：</p>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">var</span> <span class="built_in">n</span> = <span class="number">0</span>;</span><br><span class="line">do &#123;</span><br><span class="line">    <span class="built_in">n</span> = <span class="built_in">n</span> + <span class="number">1</span>;</span><br><span class="line">&#125; while (<span class="built_in">n</span> &lt; <span class="number">100</span>);</span><br><span class="line"><span class="built_in">n</span>; // <span class="number">100</span></span><br></pre></td></tr></table></figure>

<p>用<code>do &#123; ... &#125; while()</code>循环要小心，循环体会至少执行1次，而<code>for</code>和<code>while</code>循环则可能一次都不执行。</p>
<h4 id="练习-2"><a href="#练习-2" class="headerlink" title="练习"></a>练习</h4><p>请利用循环遍历数组中的每个名字，并显示<code>Hello, xxx!</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="string">&#x27;Bart&#x27;</span>, <span class="string">&#x27;Lisa&#x27;</span>, <span class="string">&#x27;Adam&#x27;</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> arr)&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">`Hello,<span class="subst">$&#123;arr[i]&#125;</span>!`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">*Hello,Bart!</span></span><br><span class="line"><span class="comment">*Hello,Lisa!</span></span><br><span class="line"><span class="comment">*Hello,Adam!</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><p>循环是让计算机做重复任务的有效的方法，有些时候，如果代码写得有问题，会让程序陷入“死循环”，也就是永远循环下去。JavaScript的死循环会让浏览器无法正常显示或执行当前页面的逻辑，有的浏览器会直接挂掉，有的浏览器会在一段时间后提示你强行终止JavaScript的执行，因此，要特别注意死循环的问题。</p>
<p>在编写循环代码时，务必小心编写初始条件和判断条件，尤其是边界值。特别注意<code>i &lt; 100</code>和<code>i &lt;= 100</code>是不同的判断逻辑。</p>
<h3 id="Map和Set"><a href="#Map和Set" class="headerlink" title="Map和Set"></a>Map和Set</h3><p>JavaScript的默认对象表示方式<code>&#123;&#125;</code>可以视为其他语言中的<code>Map</code>或<code>Dictionary</code>的数据结构，即一组键值对。</p>
<p>但是JavaScript的对象有个小问题，就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。</p>
<p>为了解决这个问题，最新的ES6规范引入了新的数据类型<code>Map</code>。要测试你的浏览器是否支持ES6规范，请执行以下代码，如果浏览器报ReferenceError错误，那么你需要换一个支持ES6的浏览器.</p>
<h4 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h4><p><code>Map</code>是一组键值对的结构，具有极快的查找速度。</p>
<p>举个例子，假设要根据同学的名字查找对应的成绩，如果用<code>Array</code>实现，需要两个<code>Array</code>：</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var names</span> = [<span class="string">&#x27;Michael&#x27;</span>, <span class="string">&#x27;Bob&#x27;</span>, <span class="string">&#x27;Tracy&#x27;</span>];</span><br><span class="line"><span class="attribute">var scores</span> = [95, 75, 85];</span><br></pre></td></tr></table></figure>

<p>给定一个名字，要查找对应的成绩，就先要在names中找到对应的位置，再从scores取出对应的成绩，Array越长，耗时越长。</p>
<p>如果用Map实现，只需要一个“名字”-“成绩”的对照表，直接根据名字查找成绩，无论这个表有多大，查找速度都不会变慢。用JavaScript写一个Map如下：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="string">&#x27;Michael&#x27;</span>, <span class="number">95</span>], [<span class="string">&#x27;Bob&#x27;</span>, <span class="number">75</span>], [<span class="string">&#x27;Tracy&#x27;</span>, <span class="number">85</span>]]);</span><br><span class="line">m.<span class="keyword">get</span>(<span class="string">&#x27;Michael&#x27;</span>); <span class="comment">// 95</span></span><br></pre></td></tr></table></figure>

<p>初始化<code>Map</code>需要一个二维数组，或者直接初始化一个空<code>Map</code>。<code>Map</code>具有以下方法：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var m = new Map(); <span class="regexp">//</span> 空Map</span><br><span class="line">m.set(<span class="string">&#x27;Adam&#x27;</span>, <span class="number">67</span>); <span class="regexp">//</span> 添加新的key-value</span><br><span class="line">m.set(<span class="string">&#x27;Bob&#x27;</span>, <span class="number">59</span>);</span><br><span class="line">m.has(<span class="string">&#x27;Adam&#x27;</span>); <span class="regexp">//</span> 是否存在key <span class="string">&#x27;Adam&#x27;</span>: true</span><br><span class="line">m.get(<span class="string">&#x27;Adam&#x27;</span>); <span class="regexp">//</span> <span class="number">67</span></span><br><span class="line">m.<span class="keyword">delete</span>(<span class="string">&#x27;Adam&#x27;</span>); <span class="regexp">//</span> 删除key <span class="string">&#x27;Adam&#x27;</span></span><br><span class="line">m.get(<span class="string">&#x27;Adam&#x27;</span>); <span class="regexp">//</span> undefined</span><br></pre></td></tr></table></figure>

<p>由于一个key只能对应一个value，所以，多次对一个key放入value，后面的值会把前面的值冲掉：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line">m.<span class="keyword">set</span>(<span class="string">&#x27;Adam&#x27;</span>, <span class="number">67</span>);</span><br><span class="line">m.<span class="keyword">set</span>(<span class="string">&#x27;Adam&#x27;</span>, <span class="number">88</span>);</span><br><span class="line">m.<span class="keyword">get</span>(<span class="string">&#x27;Adam&#x27;</span>); <span class="comment">// 88</span></span><br></pre></td></tr></table></figure>

<h4 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h4><p><code>Set</code>和<code>Map</code>类似，也是一组key的集合，但不存储value。由于key不能重复，所以，在<code>Set</code>中，没有重复的key。</p>
<p>要创建一个<code>Set</code>，需要提供一个<code>Array</code>作为输入，或者直接创建一个空<code>Set</code>：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> s<span class="number">1</span> = new Set(); // 空Set</span><br><span class="line"><span class="attribute">var</span> s<span class="number">2</span> = new Set([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]); // 含<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span></span><br></pre></td></tr></table></figure>

<p>重复元素在<code>Set</code>中自动被过滤：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> s = new Set([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">3</span>, &#x27;<span class="number">3</span>&#x27;]);</span><br><span class="line"><span class="attribute">s</span>; // Set &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="string">&quot;3&quot;</span>&#125;</span><br></pre></td></tr></table></figure>

<p>注意数字<code>3</code>和字符串<code>&#39;3&#39;</code>是不同的元素。</p>
<p>通过<code>add(key)</code>方法可以添加元素到<code>Set</code>中，可以重复添加，但不会有效果：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">s</span>.add(<span class="number">4</span>);</span><br><span class="line"><span class="attribute">s</span>; // Set &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>&#125;</span><br><span class="line"><span class="attribute">s</span>.add(<span class="number">4</span>);</span><br><span class="line"><span class="attribute">s</span>; // 仍然是 Set &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>&#125;</span><br></pre></td></tr></table></figure>

<p>通过<code>delete(key)</code>方法可以删除元素：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> s = new Set([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br><span class="line"><span class="attribute">s</span>; // Set &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;</span><br><span class="line"><span class="attribute">s</span>.delete(<span class="number">3</span>);</span><br><span class="line"><span class="attribute">s</span>; // Set &#123;<span class="number">1</span>, <span class="number">2</span>&#125;</span><br></pre></td></tr></table></figure>

<h4 id="小结-1"><a href="#小结-1" class="headerlink" title="小结"></a>小结</h4><p><code>Map</code>和<code>Set</code>是ES6标准新增的数据类型，请根据浏览器的支持情况决定是否要使用。</p>
<h3 id="iterable"><a href="#iterable" class="headerlink" title="iterable"></a>iterable</h3><p>遍历<code>Array</code>可以采用下标循环，遍历<code>Map</code>和<code>Set</code>就无法使用下标。为了统一集合类型，ES6标准引入了新的<code>iterable</code>类型，<code>Array</code>、<code>Map</code>和<code>Set</code>都属于<code>iterable</code>类型。</p>
<p>具有<code>iterable</code>类型的集合可以通过新的<code>for ... of</code>循环来遍历。</p>
<p>用<code>for ... of</code>循环遍历集合，用法如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="built_in">Set</span>([<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]);</span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="number">1</span>, <span class="string">&#x27;x&#x27;</span>], [<span class="number">2</span>, <span class="string">&#x27;y&#x27;</span>], [<span class="number">3</span>, <span class="string">&#x27;z&#x27;</span>]]);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> a) &#123; <span class="comment">// 遍历Array</span></span><br><span class="line">    <span class="built_in">console</span>.log(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> s) &#123; <span class="comment">// 遍历Set</span></span><br><span class="line">    <span class="built_in">console</span>.log(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> m) &#123; <span class="comment">// 遍历Map</span></span><br><span class="line">    <span class="built_in">console</span>.log(x[<span class="number">0</span>] + <span class="string">&#x27;=&#x27;</span> + x[<span class="number">1</span>]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>你可能会有疑问，<code>for ... of</code>循环和<code>for ... in</code>循环有何区别？</p>
<p><code>for ... in</code>循环由于历史遗留问题，它遍历的实际上是对象的属性名称。一个<code>Array</code>数组实际上也是一个对象，它的每个元素的索引被视为一个属性。</p>
<p>当我们手动给<code>Array</code>对象添加了额外的属性后，<code>for ... in</code>循环将带来意想不到的意外效果：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">a.name = <span class="string">&#x27;Hello&#x27;</span>;</span><br><span class="line">for (var <span class="meta">x</span> <span class="meta">in</span> a) &#123;</span><br><span class="line">    console<span class="meta">.log(</span><span class="meta">x</span>); // <span class="string">&#x27;0&#x27;</span>, <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;name&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>for ... in</code>循环将把<code>name</code>包括在内，但<code>Array</code>的<code>length</code>属性却不包括在内。</p>
<p><code>for ... of</code>循环则完全修复了这些问题，它只循环集合本身的元素：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">a.name = <span class="string">&#x27;Hello&#x27;</span>;</span><br><span class="line">for (var <span class="meta">x</span> of a) &#123;</span><br><span class="line">    console<span class="meta">.log(</span><span class="meta">x</span>); // <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这就是为什么要引入新的<code>for ... of</code>循环。</p>
<p>然而，更好的方式是直接使用<code>iterable</code>内置的<code>forEach</code>方法，它接收一个函数，每次迭代就自动回调该函数。以<code>Array</code>为例：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">a.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element, index, array</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// element: 指向当前元素的值</span></span><br><span class="line">    <span class="comment">// index: 指向当前索引</span></span><br><span class="line">    <span class="comment">// array: 指向Array对象本身</span></span><br><span class="line">    <span class="built_in">console</span>.log(element + <span class="string">&#x27;, index = &#x27;</span> + index);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">//A, index = 0</span></span><br><span class="line"><span class="comment">//B, index = 1</span></span><br><span class="line"><span class="comment">//C, index = 2</span></span><br></pre></td></tr></table></figure>

<p><em>注意</em>，<code>forEach()</code>方法是ES5.1标准引入的，你需要测试浏览器是否支持。</p>
<p><code>Set</code>与<code>Array</code>类似，但<code>Set</code>没有索引，因此回调函数的前两个参数都是元素本身：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="built_in">Set</span>([<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]);</span><br><span class="line">s.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element, sameElement, set</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(element);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p><code>Map</code>的回调函数参数依次为<code>value</code>、<code>key</code>和<code>map</code>本身：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="number">1</span>, <span class="string">&#x27;x&#x27;</span>], [<span class="number">2</span>, <span class="string">&#x27;y&#x27;</span>], [<span class="number">3</span>, <span class="string">&#x27;z&#x27;</span>]]);</span><br><span class="line">m.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">value, key, map</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>如果对某些参数不感兴趣，由于JavaScript的函数调用不要求参数必须一致，因此可以忽略它们。例如，只需要获得<code>Array</code>的<code>element</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">a.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(element);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><p>我们知道圆的面积计算公式为：</p>
<p>\mathrm{πr}^2<em>π</em>r2</p>
<p>当我们知道半径<code>r</code>的值时，就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> r<span class="number">1</span> = <span class="number">12</span>.<span class="number">34</span>;</span><br><span class="line"><span class="attribute">var</span> r<span class="number">2</span> = <span class="number">9</span>.<span class="number">08</span>;</span><br><span class="line"><span class="attribute">var</span> r<span class="number">3</span> = <span class="number">73</span>.<span class="number">1</span>;</span><br><span class="line"><span class="attribute">var</span> s<span class="number">1</span> = <span class="number">3</span>.<span class="number">14</span> * r<span class="number">1</span> * r<span class="number">1</span>;</span><br><span class="line"><span class="attribute">var</span> s<span class="number">2</span> = <span class="number">3</span>.<span class="number">14</span> * r<span class="number">2</span> * r<span class="number">2</span>;</span><br><span class="line"><span class="attribute">var</span> s<span class="number">3</span> = <span class="number">3</span>.<span class="number">14</span> * r<span class="number">3</span> * r<span class="number">3</span>;</span><br></pre></td></tr></table></figure>

<p>当代码出现有规律的重复的时候，你就需要当心了，每次写<code>3.14 * x * x</code>不仅很麻烦，而且，如果要把<code>3.14</code>改成<code>3.14159265359</code>的时候，得全部替换。</p>
<p>有了函数，我们就不再每次写<code>s = 3.14 * x * x</code>，而是写成更有意义的函数调用<code>s = area_of_circle(x)</code>，而函数<code>area_of_circle</code>本身只需要写一次，就可以多次调用。</p>
<p>基本上所有的高级语言都支持函数，JavaScript也不例外。JavaScript的函数不但是“头等公民”，而且可以像变量一样使用，具有非常强大的抽象能力。</p>
<h3 id="抽象"><a href="#抽象" class="headerlink" title="抽象"></a>抽象</h3><p>抽象是数学中非常常见的概念。举个例子：</p>
<p>计算数列的和，比如：<code>1 + 2 + 3 + ... + 100</code>，写起来十分不方便，于是数学家发明了求和符号∑，可以把<code>1 + 2 + 3 + ... + 100</code>记作：</p>
<p>\sum_{n=1}^{100}n∑<em>n</em>=1100<em>n</em></p>
<p>这种抽象记法非常强大，因为我们看到 ∑ 就可以理解成求和，而不是还原成低级的加法运算。</p>
<p>而且，这种抽象记法是可扩展的，比如：</p>
<p>\sum_{n=1}^{100}n^2+1∑<em>n</em>=1100<em>n</em>2+1</p>
<p>还原成加法运算就变成了：</p>
<p>(1\times1+1)+(2\times2+1)+(3\times3+1)+\dots+(100\times100+1)(1×1+1)+(2×2+1)+(3×3+1)+⋯+(100×100+1)</p>
<p>可见，借助抽象，我们才能不关心底层的具体计算过程，而直接在更高的层次上思考问题。</p>
<p>写计算机程序也是一样，函数就是最基本的一种代码抽象的方式。</p>
<h3 id="函数定义和调用"><a href="#函数定义和调用" class="headerlink" title="函数定义和调用"></a>函数定义和调用</h3><h4 id="定义函数"><a href="#定义函数" class="headerlink" title="定义函数"></a>定义函数</h4><p>在JavaScript中，定义函数的方式如下：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">function <span class="built_in">abs</span>(<span class="symbol">x</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="symbol">x</span> &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="symbol">x</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="symbol">x</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述<code>abs()</code>函数的定义如下：</p>
<ul>
<li><code>function</code>指出这是一个函数定义；</li>
<li><code>abs</code>是函数的名称；</li>
<li><code>(x)</code>括号内列出函数的参数，多个参数以<code>,</code>分隔；</li>
<li><code>&#123; ... &#125;</code>之间的代码是函数体，可以包含若干语句，甚至可以没有任何语句。</li>
</ul>
<p>请注意，函数体内部的语句在执行时，一旦执行到<code>return</code>时，函数就执行完毕，并将结果返回。因此，函数内部通过条件判断和循环可以实现非常复杂的逻辑。</p>
<p>如果没有<code>return</code>语句，函数执行完毕后也会返回结果，只是结果为<code>undefined</code>。</p>
<p>由于JavaScript的函数也是一个对象，上述定义的<code>abs()</code>函数实际上是一个函数对象，而函数名<code>abs</code>可以视为指向该函数的变量。</p>
<p>因此，第二种定义函数的方式如下：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="built_in">abs</span> = function (<span class="symbol">x</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="symbol">x</span> &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="symbol">x</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="symbol">x</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在这种方式下，<code>function (x) &#123; ... &#125;</code>是一个匿名函数，它没有函数名。但是，这个匿名函数赋值给了变量<code>abs</code>，所以，通过变量<code>abs</code>就可以调用该函数。</p>
<p>上述两种定义<em>完全等价</em>，注意第二种方式按照完整语法需要在函数体末尾加一个<code>;</code>，表示赋值语句结束。</p>
<h4 id="调用函数"><a href="#调用函数" class="headerlink" title="调用函数"></a>调用函数</h4><p>调用函数时，按顺序传入参数即可：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">abs</span>(<span class="number">10</span>); // 返回<span class="number">10</span></span><br><span class="line"><span class="attribute">abs</span>(-<span class="number">9</span>); // 返回<span class="number">9</span></span><br></pre></td></tr></table></figure>

<p>由于JavaScript允许传入任意个参数而不影响调用，因此传入的参数比定义的参数多也没有问题，虽然函数内部并不需要这些参数：</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">abs</span>(<span class="number">10</span>, <span class="string">&#x27;blablabla&#x27;</span>); <span class="comment">// 返回10</span></span><br><span class="line"><span class="keyword">abs</span>(-<span class="number">9</span>, <span class="string">&#x27;haha&#x27;</span>, <span class="string">&#x27;hehe&#x27;</span>, <span class="keyword">null</span>); <span class="comment">// 返回9</span></span><br></pre></td></tr></table></figure>

<p>传入的参数比定义的少也没有问题：</p>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">abs</span>(); <span class="comment">// 返回NaN</span></span><br></pre></td></tr></table></figure>

<p>此时<code>abs(x)</code>函数的参数<code>x</code>将收到<code>undefined</code>，计算结果为<code>NaN</code>。</p>
<p>要避免收到<code>undefined</code>，可以对参数进行检查：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">function <span class="built_in">abs</span>(<span class="symbol">x</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">typeof</span> <span class="symbol">x</span> !== <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">        throw <span class="string">&#x27;Not a number&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="symbol">x</span> &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="symbol">x</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="symbol">x</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="arguments"><a href="#arguments" class="headerlink" title="arguments"></a>arguments</h4><p>JavaScript还有一个免费赠送的关键字<code>arguments</code>，它只在函数内部起作用，并且永远指向当前函数的调用者传入的所有参数。<code>arguments</code>类似<code>Array</code>但它不是一个<code>Array</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;x = &#x27;</span> + x); <span class="comment">// 10</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>; i&lt;<span class="built_in">arguments</span>.length; i++) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;arg &#x27;</span> + i + <span class="string">&#x27; = &#x27;</span> + <span class="built_in">arguments</span>[i]); <span class="comment">// 10, 20, 30</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">foo(<span class="number">10</span>, <span class="number">20</span>, <span class="number">30</span>);</span><br></pre></td></tr></table></figure>

<p>结果</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">x</span> = <span class="number">10</span></span><br><span class="line"><span class="attribute">arg</span> <span class="number">0</span> = <span class="number">10</span></span><br><span class="line"><span class="attribute">arg</span> <span class="number">1</span> = <span class="number">20</span></span><br><span class="line"><span class="attribute">arg</span> <span class="number">2</span> = <span class="number">30</span></span><br></pre></td></tr></table></figure>

<p>利用<code>arguments</code>，你可以获得调用者传入的所有参数。也就是说，即使函数不定义任何参数，还是可以拿到参数的值：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function <span class="built_in">abs</span>() &#123;</span><br><span class="line">    <span class="keyword">if</span> (arguments.length === <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> <span class="symbol">x</span> = arguments[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">return</span> <span class="symbol">x</span> &gt;= <span class="number">0</span> ? <span class="symbol">x</span> : -<span class="symbol">x</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">abs</span>(); <span class="comment">// 0</span></span><br><span class="line"><span class="built_in">abs</span>(<span class="number">10</span>); <span class="comment">// 10</span></span><br><span class="line"><span class="built_in">abs</span>(<span class="number">-9</span>); <span class="comment">// 9</span></span><br></pre></td></tr></table></figure>

<p>实际上<code>arguments</code>最常用于判断传入参数的个数。你可能会看到这样的写法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// foo(a[, b], c)</span></span><br><span class="line"><span class="comment">// 接收2~3个参数，b是可选参数，如果只传2个参数，b默认为null：</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">a, b, c</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">arguments</span>.length === <span class="number">2</span>) &#123;</span><br><span class="line">        <span class="comment">// 实际拿到的参数是a和b，c为undefined</span></span><br><span class="line">        c = b; <span class="comment">// 把b赋给c</span></span><br><span class="line">        b = <span class="literal">null</span>; <span class="comment">// b变为默认值</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>要把中间的参数<code>b</code>变为“可选”参数，就只能通过<code>arguments</code>判断，然后重新调整参数并赋值。</p>
<h4 id="rest参数"><a href="#rest参数" class="headerlink" title="rest参数"></a>rest参数</h4><p>由于JavaScript函数允许接收任意个参数，于是我们就不得不用<code>arguments</code>来获取所有参数：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> i, rest = [];</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">arguments</span>.length &gt; <span class="number">2</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (i = <span class="number">2</span>; i&lt;<span class="built_in">arguments</span>.length; i++) &#123;</span><br><span class="line">            rest.push(<span class="built_in">arguments</span>[i]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;a = &#x27;</span> + a);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;b = &#x27;</span> + b);</span><br><span class="line">    <span class="built_in">console</span>.log(rest);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>为了获取除了已定义参数<code>a</code>、<code>b</code>之外的参数，我们不得不用<code>arguments</code>，并且循环要从索引<code>2</code>开始以便排除前两个参数，这种写法很别扭，只是为了获得额外的<code>rest</code>参数，有没有更好的方法？</p>
<p>ES6标准引入了rest参数，上面的函数可以改写为：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">(a, b, <span class="rest_arg">...rest</span>)</span> </span>&#123;</span><br><span class="line">    console.log(<span class="string">&#x27;a = &#x27;</span> + a);</span><br><span class="line">    console.log(<span class="string">&#x27;b = &#x27;</span> + b);</span><br><span class="line">    console.log(rest);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>);</span><br><span class="line"><span class="comment">// 结果:</span></span><br><span class="line"><span class="comment">// a = 1</span></span><br><span class="line"><span class="comment">// b = 2</span></span><br><span class="line"><span class="comment">// Array [ 3, 4, 5 ]</span></span><br><span class="line"></span><br><span class="line">foo(<span class="number">1</span>);</span><br><span class="line"><span class="comment">// 结果:</span></span><br><span class="line"><span class="comment">// a = 1</span></span><br><span class="line"><span class="comment">// b = undefined</span></span><br><span class="line"><span class="comment">// Array []</span></span><br></pre></td></tr></table></figure>

<p>rest参数只能写在最后，前面用<code>...</code>标识，从运行结果可知，传入的参数先绑定<code>a</code>、<code>b</code>，多余的参数以数组形式交给变量<code>rest</code>，所以，不再需要<code>arguments</code>我们就获取了全部参数。</p>
<p>如果传入的参数连正常定义的参数都没填满，也不要紧，rest参数会接收一个空数组（注意不是<code>undefined</code>）。</p>
<p>因为rest参数是ES6新标准，所以你需要测试一下浏览器是否支持。请用rest参数编写一个<code>sum()</code>函数，接收任意个参数并返回它们的和：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">...rest</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line">    rest.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element</span>) </span>&#123;</span><br><span class="line">        sum += element;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> sum;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 测试:</span></span><br><span class="line"><span class="keyword">var</span> i, args = [];</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">1</span>; i&lt;=<span class="number">100</span>; i++) &#123;</span><br><span class="line">    args.push(i);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (sum() !== <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;测试失败: sum() = &#x27;</span> + sum());</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (sum(<span class="number">1</span>) !== <span class="number">1</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;测试失败: sum(1) = &#x27;</span> + sum(<span class="number">1</span>));</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (sum(<span class="number">2</span>, <span class="number">3</span>) !== <span class="number">5</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;测试失败: sum(2, 3) = &#x27;</span> + sum(<span class="number">2</span>, <span class="number">3</span>));</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (sum.apply(<span class="literal">null</span>, args) !== <span class="number">5050</span>) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;测试失败: sum(1, 2, 3, ..., 100) = &#x27;</span> + sum.apply(<span class="literal">null</span>, args));</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;测试通过!&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="小心你的return语句"><a href="#小心你的return语句" class="headerlink" title="小心你的return语句"></a>小心你的return语句</h4><p>前面我们讲到了JavaScript引擎有一个在行末自动添加分号的机制，这可能让你栽到return语句的一个大坑：</p>
<figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title">foo</span>() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="type">&#123;</span> name: <span class="symbol">&#x27;foo</span>&#x27; &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo(); // &#123; name: <span class="symbol">&#x27;foo</span>&#x27; &#125;</span><br></pre></td></tr></table></figure>

<p>如果把return语句拆成两行：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">        &#123; name: <span class="string">&#x27;foo&#x27;</span> &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo(); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure>

<p><em>要小心了</em>，由于JavaScript引擎在行末自动添加分号的机制，上面的代码实际上变成了：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span>; <span class="comment">// 自动添加了分号，相当于return undefined;</span></span><br><span class="line">        &#123; name: <span class="string">&#x27;foo&#x27;</span> &#125;; <span class="comment">// 这行语句已经没法执行到了</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>所以正确的多行写法是：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> &#123; <span class="comment">// 这里不会自动加分号，因为&#123;表示语句尚未结束</span></span><br><span class="line">        name: <span class="string">&#x27;foo&#x27;</span></span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="变量作用域与解构赋值"><a href="#变量作用域与解构赋值" class="headerlink" title="变量作用域与解构赋值"></a>变量作用域与解构赋值</h3><p>在JavaScript中，用<code>var</code>申明的变量实际上是有作用域的。</p>
<p>如果一个变量在函数体内部申明，则该变量的作用域为整个函数体，在函数体外不可引用该变量：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line">    x = x + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">x = x + <span class="number">2</span>; <span class="comment">// ReferenceError! 无法在函数体外引用变量x</span></span><br></pre></td></tr></table></figure>

<p>如果两个不同的函数各自申明了同一个变量，那么该变量只在各自的函数体内起作用。换句话说，不同函数内部的同名变量互相独立，互不影响：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line">    x = x + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="string">&#x27;A&#x27;</span>;</span><br><span class="line">    x = x + <span class="string">&#x27;B&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由于JavaScript的函数可以嵌套，此时，内部函数可以访问外部函数定义的变量，反过来则不行：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> y = x + <span class="number">1</span>; <span class="comment">// bar可以访问foo的变量x!</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> z = y + <span class="number">1</span>; <span class="comment">// ReferenceError! foo不可以访问bar的变量y!</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果内部函数和外部函数的变量名重名怎么办？来测试一下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> x = <span class="string">&#x27;A&#x27;</span>;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;x in bar() = &#x27;</span> + x); <span class="comment">// &#x27;A&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;x in foo() = &#x27;</span> + x); <span class="comment">// 1</span></span><br><span class="line">    bar();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo();</span><br></pre></td></tr></table></figure>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">x in <span class="title">foo</span><span class="params">()</span> </span>= <span class="number">1</span></span><br><span class="line"><span class="function">x in <span class="title">bar</span><span class="params">()</span> </span>= A</span><br></pre></td></tr></table></figure>

<p>这说明JavaScript的函数在查找变量时从自身函数定义开始，从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量，则内部函数的变量将“屏蔽”外部函数的变量。</p>
<h4 id="变量提升"><a href="#变量提升" class="headerlink" title="变量提升"></a>变量提升</h4><p>JavaScript的函数定义有个特点，它会先扫描整个函数体的语句，把所有申明的变量“提升”到函数顶部：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="string">&#x27;Hello, &#x27;</span> + y;</span><br><span class="line">    <span class="built_in">console</span>.log(x);</span><br><span class="line">    <span class="keyword">var</span> y = <span class="string">&#x27;Bob&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo();</span><br></pre></td></tr></table></figure>

<p>虽然是strict模式，但语句<code>var x = &#39;Hello, &#39; + y;</code>并不报错，原因是变量<code>y</code>在稍后申明了。但是<code>console.log</code>显示<code>Hello, undefined</code>，说明变量<code>y</code>的值为<code>undefined</code>。这正是因为JavaScript引擎自动提升了变量<code>y</code>的声明，但不会提升变量<code>y</code>的赋值。</p>
<p>对于上述<code>foo()</code>函数，JavaScript引擎看到的代码相当于：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function foo() &#123;</span><br><span class="line">    <span class="keyword">var</span> <span class="symbol">y</span>; <span class="comment">// 提升变量y的申明，此时y为undefined</span></span><br><span class="line">    <span class="keyword">var</span> <span class="symbol">x</span> = <span class="string">&#x27;Hello, &#x27;</span> + <span class="symbol">y</span>;</span><br><span class="line">    console.log(<span class="symbol">x</span>);</span><br><span class="line">    <span class="symbol">y</span> = <span class="string">&#x27;Bob&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由于JavaScript的这一怪异的“特性”，我们在函数内部定义变量时，请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个<code>var</code>申明函数内部用到的所有变量：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> foo() &#123;</span><br><span class="line">    var</span><br><span class="line">        x = <span class="number">1</span>, <span class="regexp">//</span> x初始化为<span class="number">1</span></span><br><span class="line">        y = x + <span class="number">1</span>, <span class="regexp">//</span> y初始化为<span class="number">2</span></span><br><span class="line">        z, i; <span class="regexp">//</span> z和i为undefined</span><br><span class="line">    <span class="regexp">//</span> 其他语句:</span><br><span class="line">    <span class="keyword">for</span> (i=<span class="number">0</span>; i&lt;<span class="number">100</span>; i++) &#123;</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="全局作用域"><a href="#全局作用域" class="headerlink" title="全局作用域"></a>全局作用域</h4><p>不在任何函数内定义的变量就具有全局作用域。实际上，JavaScript默认有一个全局对象<code>window</code>，全局作用域的变量实际上被绑定到<code>window</code>的一个属性：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> course = <span class="string">&#x27;Learn JavaScript&#x27;</span>;</span><br><span class="line">alert(course); <span class="comment">// &#x27;Learn JavaScript&#x27;</span></span><br><span class="line">alert(<span class="built_in">window</span>.course); <span class="comment">// &#x27;Learn JavaScript&#x27;</span></span><br></pre></td></tr></table></figure>

<p>因此，直接访问全局变量<code>course</code>和访问<code>window.course</code>是完全一样的。</p>
<p>你可能猜到了，由于函数定义有两种方式，以变量方式<code>var foo = function () &#123;&#125;</code>定义的函数实际上也是一个全局变量，因此，顶层函数的定义也被视为一个全局变量，并绑定到<code>window</code>对象：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    alert(<span class="string">&#x27;foo&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo(); <span class="comment">// 直接调用foo()</span></span><br><span class="line"><span class="built_in">window</span>.foo(); <span class="comment">// 通过window.foo()调用</span></span><br></pre></td></tr></table></figure>

<h4 id="名字空间"><a href="#名字空间" class="headerlink" title="名字空间"></a>名字空间</h4><p>全局变量会绑定到<code>window</code>上，不同的JavaScript文件如果使用了相同的全局变量，或者定义了相同名字的顶层函数，都会造成命名冲突，并且很难被发现。</p>
<p>减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。例如：</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 唯一的全局变量MYAPP:</span></span><br><span class="line"><span class="keyword">var</span> MYAPP = &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其他变量:</span></span><br><span class="line">MYAPP.name = <span class="string">&#x27;myapp&#x27;</span>;</span><br><span class="line">MYAPP.version = <span class="number">1.0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其他函数:</span></span><br><span class="line">MYAPP.foo = <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;foo&#x27;</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>把自己的代码全部放入唯一的名字空间<code>MYAPP</code>中，会大大减少全局变量冲突的可能。</p>
<p>许多著名的JavaScript库都是这么干的：jQuery，YUI，underscore等等。</p>
<h4 id="局部作用域"><a href="#局部作用域" class="headerlink" title="局部作用域"></a>局部作用域</h4><p>由于JavaScript的变量作用域实际上是函数内部，我们在<code>for</code>循环等语句块中是无法定义具有局部作用域的变量的：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>; i&lt;<span class="number">100</span>; i++) &#123;</span><br><span class="line">        <span class="comment">//</span></span><br><span class="line">    &#125;</span><br><span class="line">    i += <span class="number">100</span>; <span class="comment">// 仍然可以引用变量i</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>为了解决块级作用域，ES6引入了新的关键字<code>let</code>，用<code>let</code>替代<code>var</code>可以申明一个块级作用域的变量：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i=<span class="number">0</span>; i&lt;<span class="number">100</span>; i++) &#123;</span><br><span class="line">        sum += i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// SyntaxError:</span></span><br><span class="line">    i += <span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h4><p>由于<code>var</code>和<code>let</code>申明的是变量，如果要申明一个常量，在ES6之前是不行的，我们通常用全部大写的变量来表示“这是一个常量，不要修改它的值”：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> PI = <span class="number">3</span>.<span class="number">14</span>;</span><br></pre></td></tr></table></figure>

<p>ES6标准引入了新的关键字<code>const</code>来定义常量，<code>const</code>与<code>let</code>都具有块级作用域：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> PI = <span class="number">3.14</span>;</span><br><span class="line">PI = <span class="number">3</span>; <span class="comment">// 某些浏览器不报错，但是无效果！</span></span><br><span class="line">PI; <span class="comment">// 3.14</span></span><br></pre></td></tr></table></figure>

<h4 id="解构赋值"><a href="#解构赋值" class="headerlink" title="解构赋值"></a>解构赋值</h4><p>从ES6开始，JavaScript引入了解构赋值，可以同时对一组变量进行赋值。</p>
<p>什么是解构赋值？我们先看看传统的做法，如何把一个数组的元素分别赋值给几个变量：</p>
<figure class="highlight delphi"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="keyword">array</span> = [<span class="string">&#x27;hello&#x27;</span>, <span class="string">&#x27;JavaScript&#x27;</span>, <span class="string">&#x27;ES6&#x27;</span>];</span><br><span class="line"><span class="keyword">var</span> x = <span class="keyword">array</span>[<span class="number">0</span>];</span><br><span class="line"><span class="keyword">var</span> y = <span class="keyword">array</span>[<span class="number">1</span>];</span><br><span class="line"><span class="keyword">var</span> z = <span class="keyword">array</span>[<span class="number">2</span>];</span><br></pre></td></tr></table></figure>

<p>现在，在ES6中，可以使用解构赋值，直接对多个变量同时赋值：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果浏览器支持解构赋值就不会报错:</span></span><br><span class="line"><span class="keyword">var</span> [x, y, z] = [<span class="string">&#x27;hello&#x27;</span>, <span class="string">&#x27;JavaScript&#x27;</span>, <span class="string">&#x27;ES6&#x27;</span>];</span><br><span class="line"><span class="comment">// x, y, z分别被赋值为数组对应元素:</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;x = &#x27;</span> + x + <span class="string">&#x27;, y = &#x27;</span> + y + <span class="string">&#x27;, z = &#x27;</span> + z);</span><br><span class="line"><span class="comment">//x = hello, y = JavaScript, z = ES6</span></span><br></pre></td></tr></table></figure>

<p>注意，对数组元素进行解构赋值时，多个变量要用<code>[...]</code>括起来。</p>
<p>如果数组本身还有嵌套，也可以通过下面的形式进行解构赋值，注意嵌套层次和位置要保持一致：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let [x, [y, z]] = [<span class="string">&#x27;hello&#x27;</span>, [<span class="string">&#x27;JavaScript&#x27;</span>, <span class="string">&#x27;ES6&#x27;</span>]];</span><br><span class="line">x; <span class="regexp">//</span> <span class="string">&#x27;hello&#x27;</span></span><br><span class="line">y; <span class="regexp">//</span> <span class="string">&#x27;JavaScript&#x27;</span></span><br><span class="line">z; <span class="regexp">//</span> <span class="string">&#x27;ES6&#x27;</span></span><br></pre></td></tr></table></figure>

<p>解构赋值还可以忽略某些元素：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let [, , z] = [<span class="string">&#x27;hello&#x27;</span>, <span class="string">&#x27;JavaScript&#x27;</span>, <span class="string">&#x27;ES6&#x27;</span>]; <span class="regexp">//</span> 忽略前两个元素，只对z赋值第三个元素</span><br><span class="line">z; <span class="regexp">//</span> <span class="string">&#x27;ES6&#x27;</span></span><br></pre></td></tr></table></figure>

<p>对一个对象进行解构赋值时，同样可以直接对嵌套的对象属性进行赋值，只要保证对应的层次是一致的：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">var person = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    age: <span class="number">20</span>,</span><br><span class="line">    gender: <span class="string">&#x27;male&#x27;</span>,</span><br><span class="line">    passport: <span class="string">&#x27;G-12345678&#x27;</span>,</span><br><span class="line">    school: <span class="string">&#x27;No.4 middle school&#x27;</span>,</span><br><span class="line">    address: &#123;</span><br><span class="line">        city: <span class="string">&#x27;Beijing&#x27;</span>,</span><br><span class="line">        street: <span class="string">&#x27;No.1 Road&#x27;</span>,</span><br><span class="line">        zipcode: <span class="string">&#x27;100001&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">var &#123;name, address: &#123;city, zip&#125;&#125; = person;</span><br><span class="line">name; <span class="regexp">//</span> <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">city; <span class="regexp">//</span> <span class="string">&#x27;Beijing&#x27;</span></span><br><span class="line">zip; <span class="regexp">//</span> undefined, 因为属性名是zipcode而不是zip</span><br><span class="line"><span class="regexp">//</span> 注意: address不是变量，而是为了让city和zip获得嵌套的address对象的属性:</span><br><span class="line">address; <span class="regexp">//</span> Uncaught ReferenceError: address is not defined</span><br></pre></td></tr></table></figure>

<p>使用解构赋值对对象属性进行赋值时，如果对应的属性不存在，变量将被赋值为<code>undefined</code>，这和引用一个不存在的属性获得<code>undefined</code>是一致的。如果要使用的变量名和属性名不一致，可以用下面的语法获取：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">var person = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    age: <span class="number">20</span>,</span><br><span class="line">    gender: <span class="string">&#x27;male&#x27;</span>,</span><br><span class="line">    passport: <span class="string">&#x27;G-12345678&#x27;</span>,</span><br><span class="line">    school: <span class="string">&#x27;No.4 middle school&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="regexp">//</span> 把passport属性赋值给变量id:</span><br><span class="line">let &#123;name, passport:id&#125; = person;</span><br><span class="line">name; <span class="regexp">//</span> <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">id; <span class="regexp">//</span> <span class="string">&#x27;G-12345678&#x27;</span></span><br><span class="line"><span class="regexp">//</span> 注意: passport不是变量，而是为了让变量id获得passport属性:</span><br><span class="line">passport; <span class="regexp">//</span> Uncaught ReferenceError: passport is not defined</span><br></pre></td></tr></table></figure>

<p>解构赋值还可以使用默认值，这样就避免了不存在的属性返回<code>undefined</code>的问题：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">var person = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    age: <span class="number">20</span>,</span><br><span class="line">    gender: <span class="string">&#x27;male&#x27;</span>,</span><br><span class="line">    passport: <span class="string">&#x27;G-12345678&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="regexp">//</span> 如果person对象没有single属性，默认赋值为true:</span><br><span class="line">var &#123;name, single=true&#125; = person;</span><br><span class="line">name; <span class="regexp">//</span> <span class="string">&#x27;小明&#x27;</span></span><br><span class="line">single; <span class="regexp">//</span> true</span><br></pre></td></tr></table></figure>

<p>有些时候，如果变量已经被声明了，再次赋值的时候，正确的写法也会报语法错误：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明变量:</span></span><br><span class="line"><span class="keyword">var</span> <span class="symbol">x</span>, <span class="symbol">y</span>;</span><br><span class="line"><span class="comment">// 解构赋值:</span></span><br><span class="line">&#123;<span class="symbol">x</span>, <span class="symbol">y</span>&#125; = &#123; name: <span class="string">&#x27;小明&#x27;</span>, <span class="symbol">x</span>: <span class="number">100</span>, <span class="symbol">y</span>: <span class="number">200</span>&#125;;</span><br><span class="line"><span class="comment">// 语法错误: Uncaught SyntaxError: Unexpected token =</span></span><br></pre></td></tr></table></figure>

<p>这是因为JavaScript引擎把<code>&#123;</code>开头的语句当作了块处理，于是<code>=</code>不再合法。解决方法是用小括号括起来：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(&#123;<span class="symbol">x</span>, <span class="symbol">y</span>&#125; = &#123; name: <span class="string">&#x27;小明&#x27;</span>, <span class="symbol">x</span>: <span class="number">100</span>, <span class="symbol">y</span>: <span class="number">200</span>&#125;);</span><br></pre></td></tr></table></figure>

<h4 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h4><p>解构赋值在很多时候可以大大简化代码。例如，交换两个变量<code>x</code>和<code>y</code>的值，可以这么写，不再需要临时变量：</p>
<figure class="highlight gml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="symbol">x</span>=<span class="number">1</span>, <span class="symbol">y</span>=<span class="number">2</span>;</span><br><span class="line">[<span class="symbol">x</span>, <span class="symbol">y</span>] = [<span class="symbol">y</span>, <span class="symbol">x</span>]</span><br></pre></td></tr></table></figure>

<p>快速获取当前页面的域名和路径：</p>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123;<span class="built_in">hostname</span>:<span class="built_in">domain</span>, pathname:<span class="built_in">path</span>&#125; = location;</span><br></pre></td></tr></table></figure>

<p>如果一个函数接收一个对象作为参数，那么，可以使用解构直接把对象的属性绑定到变量中。例如，下面的函数可以快速创建一个<code>Date</code>对象：</p>
<figure class="highlight processing"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function buildDate(&#123;<span class="built_in">year</span>, <span class="built_in">month</span>, <span class="built_in">day</span>, <span class="built_in">hour</span>=<span class="number">0</span>, <span class="built_in">minute</span>=<span class="number">0</span>, <span class="built_in">second</span>=<span class="number">0</span>&#125;) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Date(<span class="built_in">year</span> + <span class="string">&#x27;-&#x27;</span> + <span class="built_in">month</span> + <span class="string">&#x27;-&#x27;</span> + <span class="built_in">day</span> + <span class="string">&#x27; &#x27;</span> + <span class="built_in">hour</span> + <span class="string">&#x27;:&#x27;</span> + <span class="built_in">minute</span> + <span class="string">&#x27;:&#x27;</span> + <span class="built_in">second</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>它的方便之处在于传入的对象只需要<code>year</code>、<code>month</code>和<code>day</code>这三个属性：</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">buildDate</span>(&#123; <span class="attribute">year</span>: <span class="number">2017</span>, month: <span class="number">1</span>, day: <span class="number">1</span> &#125;);</span><br><span class="line">// <span class="selector-tag">Sun</span> <span class="selector-tag">Jan</span> 01 2017 00<span class="selector-pseudo">:00</span><span class="selector-pseudo">:00</span> <span class="selector-tag">GMT</span>+0800 (<span class="selector-tag">CST</span>)</span><br></pre></td></tr></table></figure>

<p>也可以传入<code>hour</code>、<code>minute</code>和<code>second</code>属性：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">build<span class="constructor">Date(&#123; <span class="params">year</span>: 2017, <span class="params">month</span>: 1, <span class="params">day</span>: 1, <span class="params">hour</span>: 20, <span class="params">minute</span>: 15 &#125;)</span>;</span><br><span class="line"><span class="comment">// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)</span></span><br></pre></td></tr></table></figure>

<p>使用解构赋值可以减少代码量，但是，需要在支持ES6解构赋值特性的现代浏览器中才能正常运行。目前支持解构赋值的浏览器包括Chrome，Firefox，Edge等。</p>
<h3 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h3><p>在一个对象中绑定函数，称为这个对象的方法。</p>
<p>在JavaScript中，对象的定义是这样的：</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var xiaoming</span> = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    birth: 1990</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>但是，如果我们给<code>xiaoming</code>绑定一个函数，就可以做更多的事情。比如，写个<code>age()</code>方法，返回<code>xiaoming</code>的年龄：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    birth: <span class="number">1990</span>,</span><br><span class="line">    age: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> y = <span class="keyword">new</span> <span class="built_in">Date</span>().getFullYear();</span><br><span class="line">        <span class="keyword">return</span> y - <span class="built_in">this</span>.birth;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">xiaoming.age; <span class="comment">// function xiaoming.age()</span></span><br><span class="line">xiaoming.age(); <span class="comment">// 今年调用是25,明年调用就变成26了</span></span><br></pre></td></tr></table></figure>

<p>绑定到对象上的函数称为方法，和普通函数也没啥区别，但是它在内部使用了一个<code>this</code>关键字，这个东东是什么？</p>
<p>在一个方法内部，<code>this</code>是一个特殊变量，它始终指向当前对象，也就是<code>xiaoming</code>这个变量。所以，<code>this.birth</code>可以拿到<code>xiaoming</code>的<code>birth</code>属性。</p>
<p>让我们拆开写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getAge</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> y = <span class="keyword">new</span> <span class="built_in">Date</span>().getFullYear();</span><br><span class="line">    <span class="keyword">return</span> y - <span class="built_in">this</span>.birth;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    birth: <span class="number">1990</span>,</span><br><span class="line">    age: getAge</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">xiaoming.age(); <span class="comment">// 25, 正常结果</span></span><br><span class="line">getAge(); <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure>

<p>单独调用函数<code>getAge()</code>怎么返回了<code>NaN</code>？<em>请注意</em>，我们已经进入到了JavaScript的一个大坑里。</p>
<p>JavaScript的函数内部如果调用了<code>this</code>，那么这个<code>this</code>到底指向谁？</p>
<p>答案是，视情况而定！</p>
<p>如果以对象的方法形式调用，比如<code>xiaoming.age()</code>，该函数的<code>this</code>指向被调用的对象，也就是<code>xiaoming</code>，这是符合我们预期的。</p>
<p>如果单独调用函数，比如<code>getAge()</code>，此时，该函数的<code>this</code>指向全局对象，也就是<code>window</code>。</p>
<p>坑爹啊！</p>
<h4 id="apply"><a href="#apply" class="headerlink" title="apply"></a>apply</h4><p>虽然在一个独立的函数调用中，根据是否是strict模式，<code>this</code>指向<code>undefined</code>或<code>window</code>，不过，我们还是可以控制<code>this</code>的指向的！</p>
<p>要指定函数的<code>this</code>指向哪个对象，可以用函数本身的<code>apply</code>方法，它接收两个参数，第一个参数就是需要绑定的<code>this</code>变量，第二个参数是<code>Array</code>，表示函数本身的参数。</p>
<p>用<code>apply</code>修复<code>getAge()</code>调用：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getAge</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> y = <span class="keyword">new</span> <span class="built_in">Date</span>().getFullYear();</span><br><span class="line">    <span class="keyword">return</span> y - <span class="built_in">this</span>.birth;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xiaoming = &#123;</span><br><span class="line">    name: <span class="string">&#x27;小明&#x27;</span>,</span><br><span class="line">    birth: <span class="number">1990</span>,</span><br><span class="line">    age: getAge</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">xiaoming.age(); <span class="comment">// 25</span></span><br><span class="line">getAge.apply(xiaoming, []); <span class="comment">// 25, this指向xiaoming, 参数为空</span></span><br></pre></td></tr></table></figure>

<p>另一个与<code>apply()</code>类似的方法是<code>call()</code>，唯一区别是：</p>
<ul>
<li><code>apply()</code>把参数打包成<code>Array</code>再传入；</li>
<li><code>call()</code>把参数按顺序传入。</li>
</ul>
<p>比如调用<code>Math.max(3, 5, 4)</code>，分别用<code>apply()</code>和<code>call()</code>实现如下：</p>
<figure class="highlight llvm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Math.<span class="keyword">max</span>.apply(<span class="keyword">null</span><span class="punctuation">,</span> [<span class="number">3</span><span class="punctuation">,</span> <span class="number">5</span><span class="punctuation">,</span> <span class="number">4</span>])<span class="comment">; // 5</span></span><br><span class="line">Math.<span class="keyword">max</span>.<span class="keyword">call</span>(<span class="keyword">null</span><span class="punctuation">,</span> <span class="number">3</span><span class="punctuation">,</span> <span class="number">5</span><span class="punctuation">,</span> <span class="number">4</span>)<span class="comment">; // 5</span></span><br></pre></td></tr></table></figure>

<p>对普通函数调用，我们通常把<code>this</code>绑定为<code>null</code>。</p>
<h2 id="内部对象"><a href="#内部对象" class="headerlink" title="内部对象"></a>内部对象</h2><p>在JavaScript的世界里，一切都是对象。</p>
<p>但是某些对象还是和其他对象不太一样。为了区分对象的类型，我们用<code>typeof</code>操作符获取对象的类型，它总是返回一个字符串：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">typeof <span class="number">123</span>; <span class="regexp">//</span> <span class="string">&#x27;number&#x27;</span></span><br><span class="line">typeof NaN; <span class="regexp">//</span> <span class="string">&#x27;number&#x27;</span></span><br><span class="line">typeof <span class="string">&#x27;str&#x27;</span>; <span class="regexp">//</span> <span class="string">&#x27;string&#x27;</span></span><br><span class="line">typeof true; <span class="regexp">//</span> <span class="string">&#x27;boolean&#x27;</span></span><br><span class="line">typeof undefined; <span class="regexp">//</span> <span class="string">&#x27;undefined&#x27;</span></span><br><span class="line">typeof Math.abs; <span class="regexp">//</span> <span class="string">&#x27;function&#x27;</span></span><br><span class="line">typeof null; <span class="regexp">//</span> <span class="string">&#x27;object&#x27;</span></span><br><span class="line">typeof []; <span class="regexp">//</span> <span class="string">&#x27;object&#x27;</span></span><br><span class="line">typeof &#123;&#125;; <span class="regexp">//</span> <span class="string">&#x27;object&#x27;</span></span><br></pre></td></tr></table></figure>

<p>可见，<code>number</code>、<code>string</code>、<code>boolean</code>、<code>function</code>和<code>undefined</code>有别于其他类型。特别注意<code>null</code>的类型是<code>object</code>，<code>Array</code>的类型也是<code>object</code>，如果我们用<code>typeof</code>将无法区分出<code>null</code>、<code>Array</code>和通常意义上的object——<code>&#123;&#125;</code>。</p>
<h3 id="date"><a href="#date" class="headerlink" title="date"></a>date</h3><p>在JavaScript中，<code>Date</code>对象用来表示日期和时间。</p>
<p>要获取系统当前时间，用：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">var now = <span class="keyword">new</span> <span class="constructor">Date()</span>;</span><br><span class="line">now; <span class="comment">// Wed Jun 24 2015 19:49:22 GMT+0800 (CST)</span></span><br><span class="line">now.get<span class="constructor">FullYear()</span>; <span class="comment">// 2015, 年份</span></span><br><span class="line">now.get<span class="constructor">Month()</span>; <span class="comment">// 5, 月份，注意月份范围是0~11，5表示六月</span></span><br><span class="line">now.get<span class="constructor">Date()</span>; <span class="comment">// 24, 表示24号</span></span><br><span class="line">now.get<span class="constructor">Day()</span>; <span class="comment">// 3, 表示星期三</span></span><br><span class="line">now.get<span class="constructor">Hours()</span>; <span class="comment">// 19, 24小时制</span></span><br><span class="line">now.get<span class="constructor">Minutes()</span>; <span class="comment">// 49, 分钟</span></span><br><span class="line">now.get<span class="constructor">Seconds()</span>; <span class="comment">// 22, 秒</span></span><br><span class="line">now.get<span class="constructor">Milliseconds()</span>; <span class="comment">// 875, 毫秒数</span></span><br><span class="line">now.get<span class="constructor">Time()</span>; <span class="comment">// 1435146562875, 以number形式表示的时间戳</span></span><br></pre></td></tr></table></figure>

<p>注意，当前时间是浏览器从本机操作系统获取的时间，所以不一定准确，因为用户可以把当前时间设定为任何值。</p>
<p>如果要创建一个指定日期和时间的<code>Date</code>对象，可以用：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> d = new Date(<span class="number">2015</span>, <span class="number">5</span>, <span class="number">19</span>, <span class="number">20</span>, <span class="number">15</span>, <span class="number">30</span>, <span class="number">123</span>);</span><br><span class="line"><span class="attribute">d</span>; // Fri Jun <span class="number">19</span> <span class="number">2015</span> <span class="number">20</span>:<span class="number">15</span>:<span class="number">30</span> GMT+<span class="number">0800</span> (CST)</span><br></pre></td></tr></table></figure>

<p>你可能观察到了一个<em>非常非常坑爹</em>的地方，就是JavaScript的月份范围用整数表示是0~11，<code>0</code>表示一月，<code>1</code>表示二月……，所以要表示6月，我们传入的是<code>5</code>！这绝对是JavaScript的设计者当时脑抽了一下，但是现在要修复已经不可能了。</p>
<p><code> JavaScript的Date对象月份值从0开始，牢记0=1月，1=2月，2=3月，……，11=12月。</code></p>
<p>第二种创建一个指定日期和时间的方法是解析一个符合<a target="_blank" rel="noopener" href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a>格式的字符串：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> d = Date.parse(&#x27;<span class="number">2015</span>-<span class="number">06</span>-<span class="number">24</span>T<span class="number">19</span>:<span class="number">49</span>:<span class="number">22</span>.<span class="number">875</span>+<span class="number">08</span>:<span class="number">00</span>&#x27;);</span><br><span class="line"><span class="attribute">d</span>; // <span class="number">1435146562875</span></span><br></pre></td></tr></table></figure>

<p>但它返回的不是<code>Date</code>对象，而是一个时间戳。不过有时间戳就可以很容易地把它转换为一个<code>Date</code>：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> d = new Date(<span class="number">1435146562875</span>);</span><br><span class="line"><span class="attribute">d</span>; // Wed Jun <span class="number">24</span> <span class="number">2015</span> <span class="number">19</span>:<span class="number">49</span>:<span class="number">22</span> GMT+<span class="number">0800</span> (CST)</span><br><span class="line"><span class="attribute">d</span>.getMonth(); // <span class="number">5</span></span><br></pre></td></tr></table></figure>

<p><code> 使用Date.parse()时传入的字符串使用实际月份01~12，转换为Date对象后getMonth()获取的月份值为0~11。</code></p>
<h4 id="时区"><a href="#时区" class="headerlink" title="时区"></a>时区</h4><p><code>Date</code>对象表示的时间总是按浏览器所在时区显示的，不过我们既可以显示本地时间，也可以显示调整后的UTC时间：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var</span> d = new Date(<span class="number">1435146562875</span>);</span><br><span class="line"><span class="attribute">d</span>.toLocaleString(); // &#x27;<span class="number">2015</span>/<span class="number">6</span>/<span class="number">24</span> 下午<span class="number">7</span>:<span class="number">49</span>:<span class="number">22</span>&#x27;，本地时间（北京时区+<span class="number">8</span>:<span class="number">00</span>），显示的字符串与操作系统设定的格式有关</span><br><span class="line"><span class="attribute">d</span>.toUTCString(); // &#x27;Wed, <span class="number">24</span> Jun <span class="number">2015</span> <span class="number">11</span>:<span class="number">49</span>:<span class="number">22</span> GMT&#x27;，UTC时间，与本地时间相差<span class="number">8</span>小时</span><br></pre></td></tr></table></figure>

<p>那么在JavaScript中如何进行时区转换呢？实际上，只要我们传递的是一个<code>number</code>类型的时间戳，我们就不用关心时区转换。任何浏览器都可以把一个时间戳正确转换为本地时间。</p>
<p>时间戳是个什么东西？时间戳是一个自增的整数，它表示从1970年1月1日零时整的GMT时区开始的那一刻，到现在的毫秒数。假设浏览器所在电脑的时间是准确的，那么世界上无论哪个时区的电脑，它们此刻产生的时间戳数字都是一样的，所以，时间戳可以精确地表示一个时刻，并且与时区无关。</p>
<p>所以，我们只需要传递时间戳，或者把时间戳从数据库里读出来，再让JavaScript自动转换为当地时间就可以了。</p>
<p>要获取当前时间戳，可以用：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">Date</span>.now) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">Date</span>.now()); <span class="comment">// 老版本IE没有now()方法</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">new</span> <span class="built_in">Date</span>().getTime());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="json"><a href="#json" class="headerlink" title="json"></a>json</h3><p><a target="_blank" rel="noopener" href="https://baike.baidu.com/item/JSON">JSON</a>(<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/JavaScript">JavaScript</a> Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写，同时也易于机器解析和生成，并有效地提升网络传输效率。</p>
<figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="xml">	var person=</span><span class="xquery"><span class="built_in">&#123;name</span>:<span class="string">&#x27;zjh&#x27;</span>,age:<span class="string">&#x27;11&#x27;</span>&#125;</span><span class="xml">;</span></span><br><span class="line"><span class="xml">	var json= JSON.stringify(person);</span></span><br><span class="line"><span class="xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<p><img src="https://i.loli.net/2021/03/21/PrBjehElY642iqL.png" alt="image-20210321215338151"></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;zjh&quot;</span>,<span class="attr">&quot;age&quot;</span>:<span class="string">&quot;11&quot;</span>&#125;<span class="comment">//Json格式</span></span><br></pre></td></tr></table></figure>

<h4 id="反解json"><a href="#反解json" class="headerlink" title="反解json"></a>反解json</h4><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="xml">	var person=</span><span class="xquery"><span class="built_in">&#123;name</span>:<span class="string">&#x27;zjh&#x27;</span>,age:<span class="string">&#x27;11&#x27;</span>&#125;</span><span class="xml">;</span></span><br><span class="line"><span class="xml">	var json= JSON.stringify(person);</span></span><br><span class="line"><span class="xml">	var obj=JSON.parse(json);</span></span><br><span class="line"><span class="xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<p>浏览器控制台输出</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">console</span><span class="selector-class">.log</span>(<span class="selector-tag">obj</span>);</span><br><span class="line">》&#123;<span class="attribute">name</span>: <span class="string">&quot;zjh&quot;</span>, age: <span class="string">&quot;11&quot;</span>&#125;//<span class="selector-tag">object</span>类型</span><br></pre></td></tr></table></figure>

<p>作者：zjh</p>
 
      <!-- reward -->
      
      <div id="reword-out">
        <div id="reward-btn">
          打赏
        </div>
      </div>
      
    </div>
    

    <!-- copyright -->
    
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>版权声明： </strong>
          
          本网站所有文章除特别声明外，著作权归作者所有。转载请注明出处！
          
        </li>
      </ul>
    </div>
    
    <footer class="article-footer">
       
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>

<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://cxq21.gitee.io/posts/a9ba4134.html" alt="微信分享二维码">
    </div>
</div>

<div id="share-mask"></div>  
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E5%89%8D%E7%AB%AF%E7%AC%94%E8%AE%B0/" rel="tag">前端笔记</a></li></ul>

    </footer>
  </div>

   
  <nav class="article-nav">
    
      <a href="/posts/8cde864d.html" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
          
            JavaScript高级
          
        </div>
      </a>
    
    
      <a href="/posts/c189ba0e.html" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">JavaWeb项目-网站拓展</div>
      </a>
    
  </nav>

  
      
<!-- minivaline评论 -->
<div id="mvcomments-box">
  <div id="mvcomments"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/minivaline@3/dist/MiniValine.min.js"></script>
<script>
    new MiniValine({
        el: '#mvcomments',
        appId: 'lGCocPMCSUz2tL4FcKDvFCG3-gzGzoHsz',
        appKey: 'VheJztjyMzs24xKQPGGI1bmh',
        mode: 'xCss',
        placeholder: '评论的时候建议填上您的邮箱，可以第一时间收到我的回复喔',
        pathname: window.location.pathname,
        lang: '',
        adminEmailMd5: '69b690b67d0fb9dba8ab2de5db6dd353',
        tagMeta: ["LIEFox站长", "小伙伴", "来将可留姓名"],
        master: ["69b690b67d0fb9dba8ab2de5db6dd353"],
        friends: ["1f7c8b18fb7bbe18fbaf97309de2c0ac", "e5aec373ad8a0dce7abdbe4e6585a8ba"],
        math: true,
        md: true,
        enableQQ: true,
        NoRecordIP: true,
        visitor: false,
        maxNest: 6,
        pageSize: 6,
        serverURLs: '',
        emoticonUrl: ["https://cdn.jsdelivr.net/npm/alus@latest", "https://cdn.jsdelivr.net/gh/MiniValine/qq@latest", "https://cdn.jsdelivr.net/gh/MiniValine/Bilibilis@latest", "https://cdn.jsdelivr.net/gh/MiniValine/tieba@latest", "https://cdn.jsdelivr.net/gh/MiniValine/twemoji@latest", "https://cdn.jsdelivr.net/gh/MiniValine/weibo@latest"],
    });
  const infoEle = document.querySelector('#mvcomments .info');
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
      infoEle.childNodes.forEach(function (item) {
          item.parentNode.removeChild(item);
      });
  }
</script>
<style>
	#mvcomments-box {
	padding: 5px 30px;
	}

	@media screen and (max-width: 800px) {
	#mvcomments-box {
	  padding: 5px 0px;
	}
	}

	.v .vlist .vcard .vh {
	padding-right: 20px;
	}

	.v .vlist .vcard {
	padding-left: 10px;
	}
	
	.darkmode .commentTrigger{
		background-color: #403e3e !important;
	  }
	.darkmode .MiniValine .vpage .more{
		background: #21232F
	}
	.darkmode img{
		  filter: brightness(30%)
	}
	.darkmode .MiniValine .vlist .vcard .vcomment-body .text-wrapper .vcomment.expand:before{
		background: linear-gradient(180deg, rgba(246,246,246,0), rgba(0,0,0,0.9))
	}
	.darkmode .MiniValine .vlist .vcard .vcomment-body .text-wrapper .vcomment.expand:after{
		background: rgba(0,0,0,0.9)
	}
	.darkmode .MiniValine .vlist .vcard .vcomment-body .text-wrapper .vcomment pre{
		background: #282c34
		border: 1px solid #282c34
	}
	.darkmode .MiniValine .vinputs-area .textarea-wrapper textarea{
		color: #000;
	}
	.darkmode .MiniValine .vinputs-area .auth-section .input-wrapper input{
		color: #000;
	}
	.darkmode .MiniValine .info .col .count{
		color: #000;
	}
	.darkmode .MiniValine .vinputs-area .vextra-area .vsmile-icons{
		background: transparent;
	}
</style>

 
</article>

</section>
      <footer class="footer">
  <div class="outer">
<!-- 运行天数 -->
    <ul>
        <li><span id="runtime_span"></span></li>
    </ul>

<script type="text/javascript">            
    function show_runtime() {
        window.setTimeout("show_runtime()", 1000);
        X = new Date("11/27/2020 17:17:17");
        Y = new Date();
        T = (Y.getTime() - X.getTime());
        M = 24 * 60 * 60 * 1000;
        a = T / M;
        A = Math.floor(a);
        b = (a - A) * 24;
        B = Math.floor(b);
        c = (b - B) * 60;
        C = Math.floor((b - B) * 60);
        D = Math.floor((c - C) * 60);
        runtime_span.innerHTML = "LIEFox逃脱猎人的第" + A + "天" + B + "小时" + C + "分" + D + "秒"
    }
    show_runtime();
</script>

    <ul>
      <li>
        Copyrights &copy;
        2020-2023
        <i class="ri-heart-fill heart_icon"></i> 拾柒工作室
      </li>
    </ul>


    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>访问人数:<span id="busuanzi_value_site_uv"></span></s>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>浏览次数:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
        <script type="text/javascript" src='https://s9.cnzz.com/z_stat.php?id=1279472270&amp;web_id=1279472270'></script>
        
      </li>
    </ul>
  </div>
</footer>
      <div class="float_btns">
        <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

      </div>
    </main>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/LIEFox.png" alt="LIEFox"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">时间线</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/friends">友链</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/dplayer">视频</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/update">更新日志</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/about">关于LIEFox</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="搜索">
        <i class="ri-search-line"></i>
      </a>
      
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <script>
      if (window.matchMedia("(max-width: 768px)").matches) {
        document.querySelector('.content').classList.remove('on');
        document.querySelector('.sidebar').classList.remove('on');
      }
    </script>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>感谢金主~</p>
  <div class="reward-box">
    
    
    <div class="reward-item">
      <img class="reward-img" src="/images/wechat.jpg">
      <span class="reward-type">微信</span>
    </div>
    
  </div>
</div>
    
<script src="/js/jquery-2.0.3.min.js"></script>


<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->


<script src="/js/tocbot.min.js"></script>

<script>
  tocbot.init({
    tocSelector: '.tocbot',
    contentSelector: '.article-entry',
    headingSelector: 'h1, h2, h3, h4, h5, h6',
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: 'main',
    positionFixedSelector: '.tocbot',
    positionFixedClass: 'is-position-fixed',
    fixedSidebarOffset: 'auto'
  });
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css">
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->

<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->


<script src="/js/busuanzi-2.3.pure.min.js"></script>


<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->


<script src="/js/clickBoom2.js"></script>


<!-- CodeCopy -->


<link rel="stylesheet" href="/css/clipboard.css">

<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>


<!-- CanvasBackground -->


<script src="/js/dz.js"></script>



    
  </div>
</body>

</html>